<template>
  <div class="container">
    <div class="header">
      <span class="title">直播页面</span>
    </div>
    
    <div class="main-content">
      <!-- 主画面区域 -->
      <div class="main-video-section">
        <span class="section-title">{{ liveTitle }}</span>
        <div class="main-video-wrapper">
          <!-- 主播视频播放 -->
          <div v-if="publisherSdk" class="main-video-container">
            <div v-html="publisherVideoElement"></div>
            <span class="video-label local-label">主播画面</span>
          </div>
          
          <!-- 无主播流时的占位符 -->
          <div v-else class="placeholder">
            <span v-if="status === 'connecting'">正在连接...</span>
            <span v-else-if="status === 'error'">连接错误: {{ errorMessage }}</span>
            <span v-else-if="status === 'connected'">等待主播开播...</span>
            <span v-else>等待操作...</span>
          </div>
          
          <!-- 弹幕滚动区域 - 显示在主画面区域 -->
          <div class="danmaku-container" :class="{ 'fullscreen-danmaku': isFullscreen }">
            <div 
              v-for="(item, index) in scrollingDanmakuList" 
              :key="index" 
              class="danmaku-scroll-item" 
              :style="getDanmakuStyle(item, index)"
              v-show="!item.hidden"
              @animationend="handleDanmakuEnd(item)"
            >
              {{ item.user }}：{{ item.content }}
            </div>
          </div>
          
          <!-- 全屏控制按钮 -->
          <div class="fullscreen-controls">
            <button class="fullscreen-btn" @click="toggleFullscreen">
              {{ isFullscreen ? '退出全屏' : '全屏' }}
            </button>
          </div>
          
          <!-- 全屏弹幕输入区域 -->
          <div v-if="isFullscreen" class="fullscreen-danmaku-input">
            <input 
              class="fullscreen-message-input" 
              type="text" 
              v-model="inputMessage" 
              placeholder="发送弹幕..."
              @confirm="sendMessage"
              @keyup.enter="sendMessage"
            />
            <button class="fullscreen-send-btn" @click="sendMessage">发送</button>
          </div>
        </div>
      </div>
      
      <!-- 观众画面区域 -->
      <div class="audience-video-section">
        <span class="section-title">观众画面</span>
        <div class="audience-video-wrapper">
          <!-- 本地预览（观众端自己的流） -->
          <div v-if="localStream" class="remote-video-container">
            <div v-html="localVideoElement"></div>
            <span class="video-label remote-label">我的画面</span>
          </div>
          
          <!-- 观众视频播放区域 -->
          <div 
            v-for="stream in audienceStreams" 
            :key="stream.userId" 
            class="remote-video-container"
          >
            <!-- 有流时显示视频 -->
            <div v-if="stream.hasStream" v-html="getAudienceVideoElement(stream.userId)"></div>
            
            <!-- 无流时显示占位符 -->
            <div v-else class="audience-placeholder">
              <div class="placeholder-icon">👤</div>
              <span class="placeholder-text">等待推流中...</span>
            </div>
            
            <span class="video-label remote-label">观众 {{ stream.studentName || stream.userId }}</span>
          </div>
          
          <!-- 当没有观众时显示占位符 -->
          <div v-if="audienceStreams.length === 0" class="scroll-placeholder">
            <span>暂无观众画面</span>
          </div>
        </div>
      </div>
      
      <!-- 弹幕列表区域 -->
      <div class="danmaku-list-section">
        <span class="section-title">弹幕列表</span>
        <div class="danmaku-list-wrapper" style="overflow-y: auto;">
          <div 
            v-for="(item, index) in danmakuList" 
            :key="index" 
            class="danmaku-history-item"
            :style="{ borderLeftColor: item.color }"
          >
            <span v-if="item.user" class="danmaku-history-user">{{ item.user }}：</span>
            <span class="danmaku-history-content">{{ item.content }}</span>
            <span class="danmaku-history-time">{{ formatTime(item.timestamp) }}</span>
          </div>
          
          <!-- 当没有弹幕时显示占位符 -->
          <div v-if="danmakuList.length === 0" class="danmaku-placeholder">
            <span>暂无弹幕消息</span>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 弹幕发送区域 -->
    <div class="danmaku-input-section" :class="{ 'fullscreen-input': isFullscreen }">
      <div class="input-area">
        <div class="danmaku-switch" @click="toggleDanmaku">
          <span class="switch-text">弹幕</span>
          <div class="switch-icon" :class="{ active: isDanmakuEnabled }"></div>
        </div>
        <input 
          class="message-input" 
          type="text" 
          v-model="inputMessage" 
          placeholder="说点什么..."
          @keyup.enter="sendMessage"
        />
        <button class="gift-btn" @click="openGiftPanel">🎁</button>
        <button class="send-btn" @click="sendMessage">发送</button>
      </div>
    </div>
    
    <!-- 全屏时的弹幕输入区域 -->
    <div v-if="isFullscreen" class="fullscreen-danmaku-input">
      <div class="fullscreen-input-area">
        <button class="danmaku-toggle-btn" @click="toggleDanmaku" :class="{ active: isDanmakuEnabled }">
          {{ isDanmakuEnabled ? '弹幕开' : '弹幕关' }}
        </button>
        <input 
          class="fullscreen-message-input" 
          type="text" 
          v-model="inputMessage" 
          placeholder="发送弹幕..."
          @keyup.enter="sendMessage"
        />
        <button class="fullscreen-gift-btn" @click="openGiftPanel">🎁</button>
        <button class="fullscreen-send-btn" @click="sendMessage">发送</button>
      </div>
    </div>
    
    <div class="controls">
      <button @click="joinRoom" :disabled="isConnected" class="control-btn join-btn">
        {{ isConnected ? '已连接房间' : '加入房间' }}
      </button>
      <button @click="leaveRoom" :disabled="!isConnected" class="control-btn leave-btn">
        离开房间
      </button>
    </div>
    
    <div class="room-info">
      <input 
        type="text" 
        v-model="signalServerUrl" 
        placeholder="信令服务器地址"
        class="input-field"
      />
      <input 
        type="text" 
        v-model="roomId" 
        placeholder="房间ID"
        class="input-field"
      />
      <input 
        type="text" 
        v-model="studentName" 
        placeholder="学生姓名（自动从登录信息获取）"
        class="input-field"
      />
      <input 
        type="text" 
        v-model="studentId" 
        placeholder="学生ID（自动从登录信息获取）"
        class="input-field"
      />
    </div>
    
    <div class="status-info">
      <span>状态: {{ statusText }}</span>
    </div>
    
    <!-- 签到弹窗 -->
    <div v-if="showAttendanceModal" class="attendance-modal-overlay" @click="closeAttendanceModal">
      <div class="attendance-modal" @click.stop>
        <div class="attendance-header">
          <span class="attendance-title">📋 签到通知</span>
          <span class="attendance-countdown">剩余时间: {{ attendanceCountdown }}秒</span>
        </div>
        
        <div class="attendance-content">
          <span class="attendance-message">播放者发起了签到，请确认是否参与签到</span>
          
          <!-- 摄像头画面区域 -->
          <div class="camera-section">
            <div class="camera-container">
              <video 
                ref="attendanceVideo" 
                class="attendance-video"
                autoplay 
                muted
                playsinline
              ></video>
              <canvas 
                ref="attendanceCanvas" 
                class="attendance-canvas"
                style="display: none;"
              ></canvas>
            </div>
            
            <div class="camera-controls">
              <button 
                v-if="!isCameraActive" 
                class="camera-btn start-camera-btn" 
                @click="startCamera"
              >
                📷 开启摄像头
              </button>
              <button 
                v-if="isCameraActive" 
                class="camera-btn capture-btn" 
                @click="capturePhoto"
              >
                📸 拍照签到
              </button>
              <button 
                v-if="isCameraActive" 
                class="camera-btn stop-camera-btn" 
                @click="stopCamera"
              >
                ❌ 关闭摄像头
              </button>
            </div>
            
            <!-- 拍照预览 -->
            <div v-if="capturedImage" class="photo-preview">
              <img :src="capturedImage" alt="签到照片" class="preview-image" />
              <p class="preview-text">签到照片已拍摄</p>
            </div>
          </div>
        </div>
        
        <div class="attendance-actions">
          <button 
            class="attendance-btn confirm-btn" 
            @click="confirmAttendance"
            :disabled="!capturedImage"
          >
            ✓ 确认签到
          </button>
        </div>
      </div>
    </div>
    
    <!-- 礼物选择面板 -->
    <GiftPanel 
      :isVisible="showGiftPanel" 
      @send-gift="handleSendGift"
      @close="closeGiftPanel"
    />
    
    <!-- 礼物动画容器 -->
    <div class="gift-animation-container" :class="{ 'fullscreen-gift': isFullscreen }">
      <!-- 基础礼物动画 -->
      <div 
        v-for="(gift, index) in giftAnimations" 
        :key="`gift-${index}`"
        class="gift-animation"
        :class="getGiftAnimationClass(gift)"
        :style="getGiftAnimationStyle(gift, index)"
        @animationend="removeGiftAnimation(index)"
      >
        <div class="gift-animation-content">
          <div class="gift-icon">{{ gift.icon }}</div>
          <div class="gift-text">{{ gift.user }} 送出了 {{ gift.name }}</div>
        </div>
      </div>
      
      <!-- 粒子特效 -->
      <div 
        v-for="(particle, index) in particleEffects" 
        :key="`particle-${index}`"
        class="particle-effect"
        :style="getParticleStyle(particle)"
        @animationend="removeParticleEffect(index)"
      >
        <div class="particle">{{ particle.icon }}</div>
      </div>
      
      <!-- 爆炸特效 -->
      <div 
        v-for="(explosion, index) in explosionEffects" 
        :key="`explosion-${index}`"
        class="explosion-effect"
        :style="getExplosionStyle(explosion)"
        @animationend="removeExplosionEffect(index)"
      >
        <div class="explosion-particles">
          <div class="explosion-particle" v-for="i in 8" :key="i"></div>
        </div>
      </div>
      
      <!-- 彩虹特效 -->
      <div 
        v-for="(rainbow, index) in rainbowEffects" 
        :key="`rainbow-${index}`"
        class="rainbow-effect"
        :style="getRainbowStyle(rainbow)"
        @animationend="removeRainbowEffect(index)"
      >
        <div class="rainbow-arc"></div>
      </div>
      
      <!-- 闪电特效 -->
      <div 
        v-for="(lightning, index) in lightningEffects" 
        :key="`lightning-${index}`"
        class="lightning-effect"
        :style="getLightningStyle(lightning)"
        @animationend="removeLightningEffect(index)"
      >
        <div class="lightning-bolt">⚡</div>
      </div>
      
      <!-- 神龙特效 -->
      <div 
        v-for="(dragon, index) in dragonEffects" 
        :key="`dragon-${index}`"
        class="dragon-effect"
        :style="getDragonStyle(dragon)"
        @animationend="removeDragonEffect(index)"
      >
        <div class="dragon-body">🐉</div>
      </div>
      
      <!-- 凤凰特效 -->
      <div 
        v-for="(phoenix, index) in phoenixEffects" 
        :key="`phoenix-${index}`"
        class="phoenix-effect"
        :style="getPhoenixStyle(phoenix)"
        @animationend="removePhoenixEffect(index)"
      >
        <div class="phoenix-body">🔥</div>
      </div>
      
      <!-- 星空特效 -->
      <div 
        v-for="(star, index) in starEffects" 
        :key="`star-${index}`"
        class="star-effect"
        :style="getStarStyle(star)"
        @animationend="removeStarEffect(index)"
      >
        <div class="star">✨</div>
      </div>
    </div>
  </div>
</template>

<script>
// 引入必要的库
import GiftPanel from '@/components/GiftPanel.vue'

export default {
  components: {
    GiftPanel
  },
  data() {
    return {
      // 连接相关
      signalServerUrl: 'http://1.94.105.36:3000',
      roomId: '1',
      isConnected: false,
      signalingConnection: null,
      
      // 流相关
      localStream: null,
      publisherSdk: null,
      audienceStreams: [], // 存储观众流信息
      audienceSdks: new Map(), // 使用Map存储观众SDK实例，key为userId
      connectedUsers: [], // 添加连接用户列表，用于占位
      
      // 状态相关
      status: 'idle', // idle, connecting, connected, error
      errorMessage: '',
      
      // WebRTC相关
      peerConnection: null,
      isPublishing: false,
      
      // 弹幕相关
      danmakuList: [], // 弹幕列表（历史记录）
      scrollingDanmakuList: [], // 滚动弹幕列表
      inputMessage: '', // 输入消息
      isDanmakuEnabled: true, // 弹幕开关
      danmakuScrollTop: 0, // 弹幕滚动位置
      
      // 弹幕设置
      danmakuColors: ['#ffffff', '#ff0000', '#00ff00', '#0000ff', '#ffff00', '#ff00ff'],
      selectedColor: '#ffffff',
      selectedSize: 'medium', // small, medium, large
      lastSendTime: 0, // 最后发送时间，用于防抖
      danmakuPosition: 'full', // full, top, bottom
      
      // WebSocket相关
      websocket: null,
      websocketConnected: false,
      websocketTask: null,
      
      // 签到相关
      showAttendanceModal: false,
      attendanceCountdown: 30,
      attendanceTimer: null,
      
      // 摄像头签到相关
      isCameraActive: false,
      capturedImage: null,
      attendanceStream: null,
      
      // 摄像头控制相关
      cameraEnabled: true, // 当前摄像头状态
      cameraControlPending: false, // 是否有待处理的摄像头控制指令
      lastCameraControlCommand: null, // 最后收到的摄像头控制指令
      
      // 全屏相关
      isFullscreen: false, // 是否处于全屏状态
      
      // 礼物相关
      showGiftPanel: false, // 是否显示礼物面板
      giftAnimations: [], // 礼物动画列表
      particleEffects: [], // 粒子特效列表
      explosionEffects: [], // 爆炸特效列表
      rainbowEffects: [], // 彩虹特效列表
      lightningEffects: [], // 闪电特效列表
      dragonEffects: [], // 神龙特效列表
      phoenixEffects: [], // 凤凰特效列表
      starEffects: [], // 星空特效列表
      
      // 直播标题
      liveTitle: '直播间标题AAA', // 直播标题属性
      
      // 学生信息
      studentName: '张三', // 学生姓名，用于监控统计
      studentId: '', // 学生ID，用于标识
    }
  },
  
  computed: {
    // 状态文本
    statusText() {
      switch(this.status) {
        case 'idle': return '未连接'
        case 'connecting': return '正在连接...'
        case 'connected': return '已连接房间'
        case 'error': return '连接错误: ' + this.errorMessage
        default: return '未知状态'
      }
    },
    
    // 主播视频元素
    publisherVideoElement() {
      return `<video id="publisher_video" class="video-player" controls autoplay width="100%" height="300px" style="object-fit: contain; background-color: #000;"></video>`;
    },
    
    // 本地视频元素
    localVideoElement() {
      return `<video id="local_video" class="video-player" autoplay muted playsinline width="100%" height="200px" style="object-fit: contain; background-color: #000;"></video>`;
    }
  },
  
  mounted() {
    // 从sessionStorage获取用户信息
    this.loadUserInfoFromStorage();
    
    // 动态引入SDK文件
    this.loadScript('/static/js/adapter-7.4.0.min.js').then(() => {
      return this.loadScript('/static/js/winlin.utility.js');
    }).then(() => {
      return this.loadScript('/static/js/srs.sdk.js');
    }).then(() => {
      console.log('SRS SDK 加载完成');
    }).catch((error) => {
      console.error('加载SDK失败:', error);
    });
    
    // 连接WebSocket
    this.connectWebSocket();
    
    // 监听全屏状态变化
    this.setupFullscreenListeners();
  },
  
  methods: {
    // 从多个来源加载用户信息，按优先级：URL参数 > Session存储 > 手动输入
    loadUserInfoFromStorage() {
      try {
        // 优先级1: 从URL参数获取
        const urlClassId = this.$route.params.classId;
        const urlUserId = this.$route.params.userId;
        const queryClassId = this.$route.query.classId;
        const queryUserId = this.$route.query.userId;
        
        // 获取班级ID (roomId)，并进行验证
        if (urlClassId) {
          if (this.validateClassId(urlClassId)) {
            this.roomId = urlClassId;
            console.log('从URL路径参数获取到classId:', this.roomId);
          } else {
            console.warn('URL路径参数中的classId无效:', urlClassId, '使用默认值');
          }
        } else if (queryClassId) {
          if (this.validateClassId(queryClassId)) {
            this.roomId = queryClassId;
            console.log('从URL查询参数获取到classId:', this.roomId);
          } else {
            console.warn('URL查询参数中的classId无效:', queryClassId, '使用默认值');
          }
        } else {
          // 优先级2: 从localStorage获取班级ID
          const storedClassId = localStorage.getItem('classId');
          if (storedClassId && this.validateClassId(storedClassId)) {
            this.roomId = storedClassId;
            console.log('从localStorage获取到classId:', this.roomId);
          }
          // 如果都没有或无效，保持默认值 '1'
        }
        
        // 获取用户ID (studentId)，并进行验证
        if (urlUserId) {
          if (this.validateUserId(urlUserId)) {
            this.studentId = urlUserId;
            console.log('从URL路径参数获取到userId:', this.studentId);
          } else {
            console.warn('URL路径参数中的userId无效:', urlUserId, '使用session存储');
          }
        } else if (queryUserId) {
          if (this.validateUserId(queryUserId)) {
            this.studentId = queryUserId;
            console.log('从URL查询参数获取到userId:', this.studentId);
          } else {
            console.warn('URL查询参数中的userId无效:', queryUserId, '使用session存储');
          }
        }
        
        // 如果URL参数无效或不存在，则使用session/localStorage
        if (!this.studentId) {
          // 优先级2: 从sessionStorage获取用户信息
          const userInfoStr = sessionStorage.getItem('userInfo');
          if (userInfoStr) {
            const userInfo = JSON.parse(userInfoStr);
            
            // 从userInfo中获取id和realName
            if (userInfo.id && this.validateUserId(userInfo.id)) {
              this.studentId = userInfo.id;
              console.log('从sessionStorage获取到studentId:', this.studentId);
            }
            
            if (userInfo.realName) {
              this.studentName = userInfo.realName;
              console.log('从sessionStorage获取到studentName:', this.studentName);
            }
          } else {
            // 优先级3: 从localStorage获取userId（向后兼容）
            const storedUserId = localStorage.getItem('userId');
            if (storedUserId && this.validateUserId(storedUserId)) {
              this.studentId = storedUserId;
              console.log('从localStorage获取到userId:', this.studentId);
            }
            console.log('sessionStorage中未找到userInfo，使用localStorage或默认值');
          }
        }
        
        // 如果studentName还未设置，尝试从sessionStorage获取
        if (!this.studentName) {
          const userInfoStr = sessionStorage.getItem('userInfo');
          if (userInfoStr) {
            const userInfo = JSON.parse(userInfoStr);
            if (userInfo.realName) {
              this.studentName = userInfo.realName;
              console.log('补充获取studentName:', this.studentName);
            }
          }
        }
        
        // 记录参数来源，便于调试
        const sourceInfo = {
          classId: urlClassId ? 'URL路径参数' : queryClassId ? 'URL查询参数' : localStorage.getItem('classId') ? 'localStorage存储' : '默认值',
          userId: urlUserId ? 'URL路径参数' : queryUserId ? 'URL查询参数' : sessionStorage.getItem('userInfo') ? 'sessionStorage存储' : localStorage.getItem('userId') ? 'localStorage存储' : '默认值'
        };
        
        console.log('🎯 用户信息加载完成:', {
          roomId: this.roomId,
          studentId: this.studentId,
          studentName: this.studentName,
          source: sourceInfo
        });
        
        // 在开发环境下显示来源信息提示
        if (process.env.NODE_ENV === 'development') {
          console.log(`📍 班级ID来源: ${sourceInfo.classId}`);
          console.log(`👤 用户ID来源: ${sourceInfo.userId}`);
        }
        
      } catch (error) {
        console.error('加载用户信息失败:', error);
      }
    },

    // 验证班级ID格式
    validateClassId(classId) {
      if (!classId) return false;
      // 班级ID应该是数字或字符串，长度在1-20之间
      const str = String(classId).trim();
      return str.length >= 1 && str.length <= 20 && /^[a-zA-Z0-9_-]+$/.test(str);
    },

    // 验证用户ID格式
    validateUserId(userId) {
      if (!userId) return false;
      // 用户ID应该是数字或字符串，长度在1-50之间
      const str = String(userId).trim();
      return str.length >= 1 && str.length <= 50 && /^[a-zA-Z0-9_-]+$/.test(str);
    },
    
    // 动态加载JavaScript文件
    loadScript(src) {
      return new Promise((resolve, reject) => {
        const script = document.createElement('script');
        script.src = src;
        script.onload = resolve;
        script.onerror = reject;
        document.head.appendChild(script);
      });
    },
    
    // 生成观众视频元素
    getAudienceVideoElement(userId) {
      const videoId = 'audience_video_' + userId;
      return `<video id="${videoId}" class="video-player" controls autoplay width="100%" height="150px" style="object-fit: contain; background-color: #000;"></video>`;
    },
    
    // 加入房间
    async joinRoom() {
      if (this.isConnected) return;
      
      if (!this.signalServerUrl || !this.roomId) {
        alert('请输入信令服务器地址和房间ID');
        return;
      }
      
      if (!this.studentName.trim()) {
        alert('请输入学生姓名');
        return;
      }
      
      if (!this.studentId.trim()) {
        alert('请输入学生ID');
        return;
      }
      
      try {
        this.status = 'connecting';
        
        // 连接信令服务器
        await this.connectSignalingServer();
        
        // 获取本地媒体流
        await this.getLocalStream();
        
        // 开始推流
        await this.startPublishing();
        
        this.status = 'connected';
        this.isConnected = true;
        
      } catch (error) {
        console.error('加入房间失败:', error);
        this.status = 'error';
        this.errorMessage = error.message;
        alert('加入房间失败: ' + error.message);
      }
    },
    
    // 离开房间
    leaveRoom() {
      // 停止推流
      this.stopPublishing();
      
      // 停止所有观众流播放
      this.stopAllAudienceStreams();
      
      // 断开信令服务器连接
      if (this.signalingConnection) {
        this.signalingConnection.disconnect();
        this.signalingConnection = null;
      }
      
      // 停止本地流
      if (this.localStream) {
        this.localStream.getTracks().forEach(track => track.stop());
        this.localStream = null;
      }
      
      this.status = 'idle';
      this.isConnected = false;
      this.audienceStreams = [];
      this.audienceSdks = new Map();
      this.connectedUsers = [];
    },
    
    // 添加单个观众流
    addSingleAudienceStream(userId) {
      console.log(`添加单个观众流: ${userId}`);
      
      // 检查是否已存在
      if (this.audienceStreams.find(stream => stream.userId === userId)) {
        console.log(`观众流 ${userId} 已存在，跳过添加`);
        return;
      }
      
      const streamInfo = {
        userId: userId,
        streamId: `${this.roomId}_player_${userId}`,
        studentName: null // 将在player-stream-available事件中更新
      };
      
      this.audienceStreams.push(streamInfo);
      
      // 播放观众流
      this.$nextTick(() => {
        this.playAudienceStream(userId);
      });
    },
    
    // 移除单个观众流
    removeSingleAudienceStream(userId) {
      console.log(`移除单个观众流: ${userId}`);
      
      const index = this.audienceStreams.findIndex(stream => stream.userId === userId);
      if (index !== -1) {
        // 停止SDK
        const sdk = this.audienceSdks.get(userId);
        if (sdk) {
          sdk.close();
          this.audienceSdks.delete(userId);
        }
        
        // 移除流信息
        this.audienceStreams.splice(index, 1);
        console.log(`观众流 ${userId} 已移除`);
      } else {
        console.log(`观众流 ${userId} 不存在，无需移除`);
      }
    },
    
    // 连接信令服务器
    connectSignalingServer() {
      return new Promise((resolve, reject) => {
        import('socket.io-client').then((module) => {
          const io = module.io || module.default || module;
          
          this.signalingConnection = io(this.signalServerUrl, {
            transports: ['websocket', 'polling'],
            reconnection: true,
            reconnectionAttempts: 5,
            reconnectionDelay: 1000,
            timeout: 10000
          });
          
          // 连接成功
          this.signalingConnection.on('connect', () => {
            console.log('信令服务器连接成功');
            
            // 以player身份加入房间
            this.signalingConnection.emit('join-room', {
              roomId: this.roomId,
              role: 'player',
              studentName: this.studentName,
              studentId: this.studentId
            });
            
            // 初始化摄像头控制监听器
            this.setupCameraControlListeners();
            
            resolve();
          });
          
          // 连接错误
          this.signalingConnection.on('connect_error', (error) => {
            console.error('信令服务器连接错误:', error);
            reject(new Error('信令服务器连接失败: ' + error.message));
          });
          
          // 监听房间信息
          this.signalingConnection.on('room-info', (data) => {
            console.log('房间信息:', data);
            if (data.hasPublisher) {
              // 自动播放主播流
              this.playPublisherStream();
            }
          });
          
          // 监听发布者流可用事件
          this.signalingConnection.on('publisher-stream-available', (data) => {
            console.log('发布者流可用:', data);
            // 播放主播流
            this.playPublisherStream();
          });
          
          // 监听player流可用事件
          this.signalingConnection.on('player-stream-available', (data) => {
            console.log('player流可用:', data);
            if (data.playerId !== this.signalingConnection.id) {
              // 更新用户流状态
              const user = this.connectedUsers.find(u => u.userId === data.playerId);
              if (user) {
                user.hasStream = true;
              }
              
              // 添加到观众列表，并更新studentName和studentId
              this.addAudienceStream(data.playerId, data.studentName, data.studentId);
            }
          });
          
          // 监听player流不可用事件
          this.signalingConnection.on('player-stream-unavailable', (data) => {
            console.log('player流不可用:', data);
            
            // 更新用户流状态，但保留占位
            const user = this.connectedUsers.find(u => u.userId === data.playerId);
            if (user) {
              user.hasStream = false;
            }
            
            // 停止播放流，但保留占位
            const streamInfo = this.audienceStreams.find(stream => stream.userId === data.playerId);
            if (streamInfo) {
              const sdk = this.audienceSdks.get(data.playerId);
              if (sdk) {
                sdk.close();
                this.audienceSdks.delete(data.playerId);
              }
              // 标记为无流状态，但不移除
              streamInfo.hasStream = false;
            }
          });
          
          // 监听用户连接事件
          this.signalingConnection.on('user-connected', (data) => {
            console.log('新用户连接:', data);
            
            // 添加到连接用户列表（用于占位显示）
            const existingUser = this.connectedUsers.find(user => user.userId === data.userId);
            if (!existingUser) {
              this.connectedUsers.push({
                userId: data.userId,
                role: data.role,
                hasStream: false, // 初始时没有流
                studentName: data.studentName
              });
            }
            
            // 根据变更类型精确处理，避免全量刷新
            if (data.changeType === 'player_joined') {
              // 只处理player加入，不需要刷新所有视频
              console.log(`Player ${data.userId} 加入房间`);
              
              // 为新加入的观众添加占位
              this.addAudiencePlaceholder(data.userId, data.studentName, data.studentId);
            }
          });
          
          // 监听用户断开事件
          this.signalingConnection.on('user-disconnected', (data) => {
            console.log('用户断开:', data);
            
            // 从连接用户列表中移除
            const index = this.connectedUsers.findIndex(user => user.userId === data.userId);
            if (index !== -1) {
              this.connectedUsers.splice(index, 1);
            }
            
            // 根据变更类型精确处理，避免全量刷新
            if (data.changeType === 'player_left') {
              // 只移除特定用户的流，不刷新所有视频
              this.removeSingleAudienceStream(data.userId);
            }
          });
          
          // 监听错误
          this.signalingConnection.on('error', (data) => {
            console.error('信令服务器错误:', data);
          });
          
          // 监听签到请求
          this.signalingConnection.on('attendance-request', (data) => {
            console.log('收到签到请求:', data);
            this.showAttendanceRequest(data);
          });
          
          // 监听签到取消
          this.signalingConnection.on('attendance-cancelled', (data) => {
            console.log('签到已取消:', data);
            if (this.showAttendanceModal) {
              this.closeAttendanceModal();
              alert('签到已取消');
            }
          });
          
        }).catch((error) => {
          reject(new Error('Socket.IO加载失败: ' + error.message));
        });
      });
    },
    
    // 获取本地媒体流
    async getLocalStream() {
      try {
        this.localStream = await navigator.mediaDevices.getUserMedia({
          audio: true,
          video: true
        });
        
        // 设置到本地视频元素
        this.$nextTick(() => {
          const localVideo = document.getElementById('local_video');
          if (localVideo) {
            localVideo.srcObject = this.localStream;
          }
        });
        
      } catch (error) {
        throw new Error('获取摄像头权限失败: ' + error.message);
      }
    },
    
    // 开始推流
    async startPublishing() {
      if (!this.localStream || !this.signalingConnection) {
        return;
      }
      
      try {
        // 创建RTCPeerConnection
        this.peerConnection = new RTCPeerConnection({
          iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
        });
        
        // 添加本地流
        this.localStream.getTracks().forEach(track => {
          this.peerConnection.addTrack(track, this.localStream);
        });
        
        // 创建offer
        const offer = await this.peerConnection.createOffer();
        await this.peerConnection.setLocalDescription(offer);
        
        // 发送player推流offer到信令服务器
        this.signalingConnection.emit('player-publish-offer', {
          sdp: offer.sdp,
          type: offer.type,
          roomId: this.roomId
        });
        
        // 监听player推流answer
        this.signalingConnection.on('player-publish-answer', (data) => {
          this.handlePublishAnswer(data);
        });
        
        this.isPublishing = true;
        
      } catch (error) {
        console.error('推流失败:', error);
        throw error;
      }
    },
    
    // 处理推流answer
    async handlePublishAnswer(data) {
      try {
        const answer = new RTCSessionDescription({
          type: 'answer',
          sdp: data.sdp
        });
        await this.peerConnection.setRemoteDescription(answer);
        console.log('推流连接建立成功');
      } catch (error) {
        console.error('处理推流answer失败:', error);
      }
    },
    
    // 停止推流
    stopPublishing() {
      if (this.peerConnection) {
        this.peerConnection.close();
        this.peerConnection = null;
      }
      this.isPublishing = false;
    },
    
    // 播放主播流
    async playPublisherStream() {
      try {
        // 创建SDK实例播放主播流
        if (this.publisherSdk) {
          this.publisherSdk.close();
        }
        
        this.publisherSdk = new SrsRtcWhipWhepAsync();
        
        // 构建播放URL
        const publisherStreamId = `${this.roomId}_publisher`;
        const playUrl = `http://1.94.105.36:1985/rtc/v1/whep/?app=live&stream=${publisherStreamId}`;
        
        // 开始播放
        await this.publisherSdk.play(playUrl);
        
        // 设置到视频元素
        this.$nextTick(() => {
          const publisherVideo = document.getElementById('publisher_video');
          if (publisherVideo) {
            publisherVideo.srcObject = this.publisherSdk.stream;
            publisherVideo.play().catch(error => {
              console.warn('主播视频播放被阻止:', error);
            });
          }
        });
        
        console.log('主播流播放成功');
        
      } catch (error) {
        console.error('播放主播流失败:', error);
      }
    },
    
    // 添加观众占位
    addAudiencePlaceholder(userId, studentName = null, studentId = null) {
      // 检查是否已存在
      if (this.audienceStreams.find(stream => stream.userId === userId)) {
        return;
      }
      
      const streamInfo = {
        userId: userId,
        streamId: `${this.roomId}_player_${userId}`,
        hasStream: false, // 初始时没有流
        studentName: studentName,
        studentId: studentId
      };
      
      this.audienceStreams.push(streamInfo);
    },
    
    // 添加观众流
    addAudienceStream(userId, studentName = null, studentId = null) {
      // 检查是否已存在占位
      const existingStream = this.audienceStreams.find(stream => stream.userId === userId);
      if (existingStream) {
        // 更新为有流状态、studentName和studentId
        existingStream.hasStream = true;
        if (studentName) {
          existingStream.studentName = studentName;
        }
        if (studentId) {
          existingStream.studentId = studentId;
        }
      } else {
        // 创建新的流信息
        const streamInfo = {
          userId: userId,
          streamId: `${this.roomId}_player_${userId}`,
          hasStream: true,
          studentName: studentName,
          studentId: studentId
        };
        this.audienceStreams.push(streamInfo);
      }
      
      // 播放观众流
      this.$nextTick(() => {
        this.playAudienceStream(userId);
      });
    },
    
    // 播放观众流
    async playAudienceStream(userId) {
      try {
        const streamInfo = this.audienceStreams.find(stream => stream.userId === userId);
        if (!streamInfo) return;
        
        // 创建SDK实例
        const sdk = new SrsRtcWhipWhepAsync();
        
        // 构建播放URL
        const playUrl = `http://1.94.105.36:1985/rtc/v1/whep/?app=live&stream=${streamInfo.streamId}`;
        
        // 开始播放
        await sdk.play(playUrl);
        
        // 保存SDK实例
        this.audienceSdks.set(userId, sdk);
        
        // 设置到视频元素
        const videoId = 'audience_video_' + userId;
        const videoElement = document.getElementById(videoId);
        if (videoElement) {
          videoElement.srcObject = sdk.stream;
          videoElement.play().catch(error => {
            console.warn('观众视频播放被阻止:', error);
          });
        }
        
        console.log('观众流播放成功:', userId);
        
      } catch (error) {
        console.error('播放观众流失败:', error);
      }
    },
    
    // 移除观众流
    removeAudienceStream(userId) {
      const index = this.audienceStreams.findIndex(stream => stream.userId === userId);
      if (index !== -1) {
        // 停止SDK
        const sdk = this.audienceSdks.get(userId);
        if (sdk) {
          sdk.close();
          this.audienceSdks.delete(userId);
        }
        
        // 移除流信息
        this.audienceStreams.splice(index, 1);
      }
    },
    
    // 停止所有观众流
    stopAllAudienceStreams() {
      this.audienceSdks.forEach(sdk => {
        if (sdk) {
          sdk.close();
        }
      });
      
      if (this.publisherSdk) {
        this.publisherSdk.close();
        this.publisherSdk = null;
      }
      
      this.audienceSdks.clear();
      this.audienceStreams = [];
    },
    
    // 格式化时间
    formatTime(timestamp) {
      if (!timestamp) return '';
      const date = new Date(timestamp);
      return `${date.getHours().toString().padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}`;
    },
    
    // 添加弹幕到列表
    addDanmaku(content, user = '用户', color = '#ffffff') {
      const danmaku = {
        content: content,
        user: user,
        color: color,
        timestamp: Date.now()
      };
      // 使用unshift将新弹幕添加到数组开头，让最新的弹幕显示在上方
      this.danmakuList.unshift(danmaku);
      
      // 限制弹幕数量，避免过多影响性能
      if (this.danmakuList.length > 100) {
        this.danmakuList.pop(); // 从末尾删除最旧的弹幕
      }
    },
    
    
    // 添加滚动弹幕
    addScrollingDanmaku(content, user = '用户', color = '#ffffff') {
      // 全屏模式下弹幕在上半屏随机位置，正常模式下正常显示
      const topPosition = this.isFullscreen 
        ? Math.floor(Math.random() * 300) + 50  // 全屏时在上半屏随机位置50-350px
        : Math.floor(Math.random() * 300) + 100; // 正常模式下在100-400px区域
      
      console.log(`添加弹幕 - 全屏: ${this.isFullscreen}, 计算位置: ${topPosition}, 内容: ${content}`);
      
      const danmaku = {
        content: content,
        user: user,
        color: color,
        top: topPosition, // 使用计算后的位置
        fontSize: this.getFontSize(),
        timestamp: Date.now(),
        hidden: false
      };
      
      this.scrollingDanmakuList.push(danmaku);
      console.log('添加滚动弹幕:', danmaku.content, '位置:', danmaku.top);
      console.log('当前滚动弹幕列表长度:', this.scrollingDanmakuList.length);
      console.log('滚动弹幕列表:', this.scrollingDanmakuList);
      
      // 限制滚动弹幕数量，避免过多影响性能
      if (this.scrollingDanmakuList.length > 50) {
        this.scrollingDanmakuList.shift();
      }
    },
    
    // 获取字体大小
    getFontSize() {
      const fontSizeMap = {
        small: 12,
        medium: 16,
        large: 20
      };
      return fontSizeMap[this.selectedSize] || 16;
    },
    
    // 获取弹幕样式
    getDanmakuStyle(item, index) {
      console.log(`弹幕样式应用 - 内容: ${item.content}, top值: ${item.top}, 全屏: ${this.isFullscreen}`);
      
      return {
        color: item.color,
        fontSize: item.fontSize + 'px',
        top: item.top + 'px', // 直接使用弹幕数据中的top值
        left: '100%' // 从右侧开始
      };
    },
    
    // 处理弹幕动画结束
    handleDanmakuEnd(item) {
      try {
        item.hidden = true;
      } catch (e) {
        console.error('隐藏弹幕失败', e);
      }
    },
    
    // 切换弹幕开关
    toggleDanmaku() {
      this.isDanmakuEnabled = !this.isDanmakuEnabled;
    },
    
    // 获取当前登录用户信息
    getCurrentUserInfo() {
      try {
        // 从localStorage获取userId
        const userId = localStorage.getItem('userId') || '103';
        
        // 从sessionStorage获取用户详细信息
        const userInfoStr = sessionStorage.getItem('userInfo');
        let userName = '用户';
        
        if (userInfoStr) {
          const userInfo = JSON.parse(userInfoStr);
          console.log('用户信息字段:', {
            name: userInfo.name,
            nickname: userInfo.nickname,
            username: userInfo.username
          });
          // 优先使用nickname（真实姓名），然后是name，最后是默认值
          userName = userInfo.nickname || userInfo.name || userName;
          console.log('选择的用户名:', userName);
        }
        
        return {
          userId: userId,
          userName: userName
        };
      } catch (error) {
        console.error('获取用户信息失败:', error);
        return {
          userId: '103',
          userName: '用户'
        };
      }
    },

    // 发送消息
    sendMessage() {
      if (!this.inputMessage.trim()) {
        alert('请输入弹幕内容');
        return;
      }
      
      // 防抖机制：防止短时间内多次发送
      const now = Date.now();
      if (this.lastSendTime && (now - this.lastSendTime) < 1000) {
        console.log('发送过于频繁，跳过此次发送');
        return;
      }
      this.lastSendTime = now;
      
      // 获取当前用户信息
      const currentUser = this.getCurrentUserInfo();
      
      // 优先使用WebSocket发送
      if (this.isDanmakuEnabled && this.websocket && this.websocketConnected) {
        const danmakuMessage = {
          type: 'danmaku',
          content: this.inputMessage,
          user: currentUser.userName,
          toUserid: currentUser.userId,
          timestamp: Date.now()
        };

        // 通过WebSocket发送弹幕
        this.websocket.send(JSON.stringify(danmakuMessage));
        console.log('弹幕已通过WebSocket发送:', danmakuMessage);
        
        // 不在这里本地显示，等待WebSocket回显
      } else {
        // WebSocket不可用时，本地发送
        this.addDanmaku(this.inputMessage, currentUser.userName, this.selectedColor);
        this.addScrollingDanmaku(this.inputMessage, currentUser.userName, this.selectedColor);
        console.log('弹幕已本地发送:', this.inputMessage);
      }
      
      // 清空输入框
      this.inputMessage = '';
      
      // 显示发送成功提示
      console.log('弹幕发送成功');
    },
    
    // 连接WebSocket
    connectWebSocket() {
      try {
        // 使用动态获取的班级ID（roomId）
        const classId = this.roomId || '101'; // 如果没有roomId，使用默认值101
        const wsUrl = `ws://localhost:9006/danmaku-ws?classId=${classId}`;
        
        console.log('正在连接WebSocket:', wsUrl);
        this.websocket = new WebSocket(wsUrl);

        // 监听WebSocket连接打开事件
        this.websocket.onopen = () => {
          console.log('WebSocket连接已打开');
          this.websocketConnected = true;
        };

        // 监听WebSocket消息接收事件
        this.websocket.onmessage = (event) => {
          try {
            let data = event.data;
            console.log('收到WebSocket消息:', event.data);
            
            // 检查是否是服务器回复的消息格式
            if (typeof data === 'string' && data.startsWith('服务器回复: ')) {
              const jsonStr = data.substring('服务器回复: '.length);
              data = JSON.parse(jsonStr);
            } else if (typeof data === 'string') {
              data = JSON.parse(data);
            }

            // 添加消息去重逻辑（检查最近5秒内的相同内容）
            const isDuplicate = this.danmakuList.some(item => {
              const timeDiff = Math.abs((item.timestamp || 0) - (data.timestamp || Date.now()));
              return item.content === data.content && 
                     item.user === (data.user || data.userName) &&
                     timeDiff < 5000; // 5秒内的相同内容和用户视为重复
            });

            if (isDuplicate) {
              console.log('过滤重复消息:', data);
              return;
            }

            // 处理不同类型的WebSocket消息
            if (data.type === 'danmaku') {
              const user = data.user || data.userName;
              const color = data.color || (data.isGift ? '#FFD700' : '#ffffff');
              const content = data.content;

              if (content && content.trim()) {
                // 添加到历史弹幕列表
                this.addDanmaku(content, user, color);
                // 添加到滚动弹幕列表（位置在addScrollingDanmaku中计算）
                this.addScrollingDanmaku(content, user, color);
                
                // 如果是礼物消息，同时显示礼物动画
                console.log('检查礼物消息:', {
                  isGift: data.isGift,
                  giftId: data.giftId,
                  content: data.content,
                  fullData: data
                });
                
                if (data.isGift && data.giftId) {
                  const giftData = {
                    id: data.giftId,
                    name: data.giftName,
                    icon: data.giftIcon,
                    price: data.giftPrice,
                    category: data.giftCategory
                  };
                  console.log('显示礼物动画:', giftData);
                  this.showGiftAnimation(giftData, user);
                } else if (data.content && data.content.includes('🎁')) {
                  // 如果消息包含礼物emoji但没有isGift标记，尝试解析礼物信息
                  console.log('检测到礼物消息但没有isGift标记，尝试解析:', data.content);
                  this.parseAndShowGiftFromContent(data.content, user);
                }
                
                console.log('WebSocket弹幕已添加:', content);
              }
            }
            // 处理AI助手回复
            else if (data.type === 'ai_reply') {
              const content = data.content;
              const user = 'AI助手';
              const color = '#00ff00'; // AI回复使用绿色

              if (content && content.trim()) {
                this.addDanmaku(content, user, color);
                this.addScrollingDanmaku(content, user, color);
                
                // AI回答完成后5秒触发消息查询
                this.triggerMessageQuery(5000);
                console.log('AI助手回复完成，将在5秒后触发消息查询');
              }
            }
          } catch (e) {
            // 如果不是JSON格式，则作为普通文本处理
            console.log('收到WebSocket文本消息:', event.data);

            const isDuplicate = this.danmakuList.some(item =>
              item.content === event.data &&
              (Date.now() - (item.timestamp || 0)) < 1000
            );

            if (isDuplicate) {
              console.log('过滤重复文本消息:', event.data);
              return;
            }

            const content = event.data;
            const user = '系统';
            const color = '#ffffff';

            if (content && content.trim()) {
              this.addDanmaku(content, user, color);
              this.addScrollingDanmaku(content, user, color);
            }
          }
        };

        // 监听WebSocket关闭事件
        this.websocket.onclose = () => {
          console.log('WebSocket连接已关闭');
          this.websocketConnected = false;
        };

        // 监听WebSocket错误事件
        this.websocket.onerror = (error) => {
          console.error('WebSocket错误:', error);
          this.websocketConnected = false;
        };
      } catch (error) {
        console.error('WebSocket连接初始化失败:', error);
      }
    },
    

    // 触发消息查询（通知MessageNotification组件）
    triggerMessageQuery(delay = 0) {
      if (delay > 0) {
        console.log(`将在${delay/1000}秒后触发消息查询`);
        setTimeout(() => {
          this.triggerMessageQuery(0); // 延迟后调用不带延迟的版本
        }, delay);
        return;
      }
      
      // 发送自定义事件到window，让MessageNotification组件监听
      const event = new CustomEvent('triggerMessageQuery', {
        detail: { 
          source: 'ai_response',
          timestamp: Date.now()
        }
      });
      window.dispatchEvent(event);
      console.log('已触发消息查询事件');
    },
    
    // 显示签到弹窗
    showAttendanceRequest(data) {
      console.log('收到签到请求:', data);
      this.showAttendanceModal = true;
      this.attendanceCountdown = (data.duration)/1000;
      
      // 开始倒计时
      this.attendanceTimer = setInterval(() => {
        this.attendanceCountdown--;
        if (this.attendanceCountdown <= 0) {
          this.closeAttendanceModal();
        }
      }, 1000);
      
      // 播放提示音或震动
      console.log('签到请求提示');
    },
    
    // 确认签到
    async confirmAttendance() {
      if (!this.capturedImage) {
        alert('请先拍照');
        return;
      }

      try {
        // 导入签到API
        const { signinApiService, signinUtils } = await import('@/api/signin');
        
        // 将base64图片转换为Blob
        const imageBlob = await signinApiService.dataURLtoBlob(this.capturedImage);
        
        // 压缩图片
        const compressedImage = await signinApiService.compressImage(imageBlob);
        
        // 准备签到数据
        const signinData = {
          image: compressedImage,
          userId: signinUtils.getCurrentUserId(),
          liveName: this.liveTitle  // 使用当前直播间的标题
        };
        
        console.log('开始提交签到...');
        
        // 调用签到API
        const result = await signinApiService.signIn(signinData);
        
        if (result.success) {
          console.log('签到成功，相似度:', result.data);
          
          // 发送签到响应到信令服务器
          if (this.signalingConnection) {
            this.signalingConnection.emit('attendance-response', {
              roomId: this.roomId,
              attended: true,
              similarity: result.data
            });
          }
          
          this.closeAttendanceModal();
        } else {
          console.error('签到失败:', result.message);
        }
      } catch (error) {
        console.error('签到过程中发生错误:', error);
        
        // 即使API调用失败，也发送签到响应到信令服务器
        if (this.signalingConnection) {
          this.signalingConnection.emit('attendance-response', {
            roomId: this.roomId,
            attended: true
          });
        }
        
        this.closeAttendanceModal();
      }
    },
    
    // 关闭签到弹窗
    closeAttendanceModal() {
      this.showAttendanceModal = false;
      
      // 清理倒计时
      if (this.attendanceTimer) {
        clearInterval(this.attendanceTimer);
        this.attendanceTimer = null;
      }
      
      // 停止摄像头
      this.stopCamera();
      
      // 如果是超时关闭，发送未确认响应
      if (this.attendanceCountdown <= 0 && this.signalingConnection) {
        this.signalingConnection.emit('attendance-response', {
          roomId: this.roomId,
          attended: false
        });
        console.log('签到超时，已发送未确认响应');
      }
    },
    
    // 启动摄像头
    async startCamera() {
      try {
        this.attendanceStream = await navigator.mediaDevices.getUserMedia({
          video: { 
            width: { ideal: 640 },
            height: { ideal: 480 },
            facingMode: 'user' // 前置摄像头
          },
          audio: false
        });
        
        const video = this.$refs.attendanceVideo;
        if (video) {
          video.srcObject = this.attendanceStream;
          this.isCameraActive = true;
          console.log('摄像头启动成功');
        }
      } catch (error) {
        console.error('启动摄像头失败:', error);
        alert('无法访问摄像头，请检查权限设置');
      }
    },
    
    // 停止摄像头
    stopCamera() {
      if (this.attendanceStream) {
        this.attendanceStream.getTracks().forEach(track => {
          track.stop();
        });
        this.attendanceStream = null;
      }
      
      const video = this.$refs.attendanceVideo;
      if (video) {
        video.srcObject = null;
      }
      
      this.isCameraActive = false;
      this.capturedImage = null;
      console.log('摄像头已关闭');
    },
    
    // 拍照
    capturePhoto() {
      const video = this.$refs.attendanceVideo;
      const canvas = this.$refs.attendanceCanvas;
      
      if (!video || !canvas) {
        console.error('摄像头或画布未准备好');
        alert('摄像头未准备好，请重试');
        return;
      }
      
      if (video.videoWidth === 0 || video.videoHeight === 0) {
        console.error('视频尺寸无效');
        alert('视频未加载完成，请稍后重试');
        return;
      }
      
      try {
        const context = canvas.getContext('2d');
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        
        // 绘制视频帧到canvas
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        
        // 转换为base64图片
        this.capturedImage = canvas.toDataURL('image/jpeg', 0.8);
        console.log('拍照成功，图片大小:', this.capturedImage.length, '字符');
        
        // 显示成功提示
        this.$message?.success('拍照成功！');
      } catch (error) {
        console.error('拍照失败:', error);
        alert('拍照失败，请重试');
      }
    },
    
    // 处理摄像头控制指令
    handleCameraControlCommand(data) {
      const { roomId, action, timestamp } = data;
      
      console.log('收到摄像头控制指令:', data);
      
      // 验证房间ID
      if (roomId !== this.roomId) {
        console.warn('忽略其他房间的摄像头控制指令');
        return;
      }
      
      // 记录控制指令
      this.lastCameraControlCommand = data;
      this.cameraControlPending = true;
      
      // 执行摄像头控制
      this.executeCameraControl(action)
        .then((success) => {
          // 发送响应给服务器
          this.sendCameraControlResponse(action, success, null);
        })
        .catch((error) => {
          console.error('执行摄像头控制失败:', error);
          // 发送失败响应给服务器
          this.sendCameraControlResponse(action, false, error.message);
        })
        .finally(() => {
          this.cameraControlPending = false;
        });
    },
    
    // 执行摄像头控制
    async executeCameraControl(action) {
      try {
        if (action === 'enable') {
          // 开启摄像头
          if (!this.cameraEnabled) {
            await this.enableCamera();
            this.cameraEnabled = true;
            alert('摄像头已开启');
          }
          return true;
        } else if (action === 'disable') {
          // 关闭摄像头
          if (this.cameraEnabled) {
            await this.disableCamera();
            this.cameraEnabled = false;
            alert('摄像头已关闭');
          }
          return true;
        }
        return false;
      } catch (error) {
        console.error('摄像头控制操作失败:', error);
        throw error;
      }
    },
    
    // 开启摄像头
    async enableCamera() {
      try {
        // 如果已有本地流，先停止
        if (this.localStream) {
          this.stopLocalStream();
        }
        
        // 重新获取媒体流
        await this.startLocalStream();
        
        console.log('摄像头已开启');
      } catch (error) {
        console.error('开启摄像头失败:', error);
        throw new Error('无法开启摄像头: ' + error.message);
      }
    },
    
    // 关闭摄像头
    async disableCamera() {
      try {
        // 停止本地流
        this.stopLocalStream();
        
        console.log('摄像头已关闭');
      } catch (error) {
        console.error('关闭摄像头失败:', error);
        throw new Error('无法关闭摄像头: ' + error.message);
      }
    },

    // 启动本地媒体流
    async startLocalStream() {
      try {
        this.localStream = await navigator.mediaDevices.getUserMedia({
          audio: true,
          video: true
        });
        
        // 设置到本地视频元素
        this.$nextTick(() => {
          const localVideo = document.getElementById('local_video');
          if (localVideo) {
            localVideo.srcObject = this.localStream;
          }
        });
        
        console.log('本地媒体流已启动');
      } catch (error) {
        console.error('启动本地媒体流失败:', error);
        throw new Error('获取摄像头权限失败: ' + error.message);
      }
    },

    // 停止本地媒体流
    stopLocalStream() {
      try {
        if (this.localStream) {
          this.localStream.getTracks().forEach(track => {
            track.stop();
          });
          this.localStream = null;
          
          // 清除本地视频元素
          this.$nextTick(() => {
            const localVideo = document.getElementById('local_video');
            if (localVideo) {
              localVideo.srcObject = null;
            }
          });
          
          console.log('本地媒体流已停止');
        }
      } catch (error) {
        console.error('停止本地媒体流失败:', error);
        throw error;
      }
    },
    
    // 发送摄像头控制响应
    sendCameraControlResponse(action, success, error) {
      if (!this.signalingConnection) {
        console.error('信令连接未建立，无法发送摄像头控制响应');
        return;
      }
      
      const responseData = {
        roomId: this.roomId,
        action: action,
        success: success,
        error: error
      };
      
      // 发送Socket.IO事件
      this.signalingConnection.emit('camera-control-response', responseData);
      
      console.log('摄像头控制响应已发送:', responseData);
    },
    
    // 初始化摄像头控制事件监听
    setupCameraControlListeners() {
      if (!this.signalingConnection) {
        console.error('信令连接未建立，无法设置摄像头控制监听器');
        return;
      }
      
      // 监听摄像头控制指令
      this.signalingConnection.on('camera-control-command', (data) => {
        this.handleCameraControlCommand(data);
      });
      
      console.log('摄像头控制事件监听器已设置');
    },
    
    // 切换全屏状态
    toggleFullscreen() {
      this.isFullscreen = !this.isFullscreen;
      
      if (this.isFullscreen) {
        // 进入全屏
        this.enterFullscreen();
      } else {
        // 退出全屏
        this.exitFullscreen();
      }
    },
    
    // 进入全屏
    enterFullscreen() {
      try {
        const videoContainer = document.querySelector('.main-video-wrapper');
        if (videoContainer) {
          if (videoContainer.requestFullscreen) {
            videoContainer.requestFullscreen();
          } else if (videoContainer.webkitRequestFullscreen) {
            videoContainer.webkitRequestFullscreen();
          } else if (videoContainer.mozRequestFullScreen) {
            videoContainer.mozRequestFullScreen();
          } else if (videoContainer.msRequestFullscreen) {
            videoContainer.msRequestFullscreen();
          }
          
          // 全屏后调整视频尺寸
          this.$nextTick(() => {
            this.adjustVideoForFullscreen();
          });
        }
      } catch (error) {
        console.error('进入全屏失败:', error);
        // 如果浏览器全屏失败，使用自定义全屏
        this.isFullscreen = true;
        this.adjustVideoForFullscreen();
      }
    },
    
    // 退出全屏
    exitFullscreen() {
      try {
        if (document.exitFullscreen) {
          document.exitFullscreen();
        } else if (document.webkitExitFullscreen) {
          document.webkitExitFullscreen();
        } else if (document.mozCancelFullScreen) {
          document.mozCancelFullScreen();
        } else if (document.msExitFullscreen) {
          document.msExitFullscreen();
        }
      } catch (error) {
        console.error('退出全屏失败:', error);
        // 如果浏览器全屏失败，使用自定义全屏
        this.isFullscreen = false;
      }
    },
    
    // 设置全屏状态监听
    setupFullscreenListeners() {
      // 监听全屏状态变化
      const fullscreenChangeEvents = [
        'fullscreenchange',
        'webkitfullscreenchange',
        'mozfullscreenchange',
        'MSFullscreenChange'
      ];
      
      fullscreenChangeEvents.forEach(event => {
        document.addEventListener(event, () => {
          this.handleFullscreenChange();
        });
      });
    },
    
    // 处理全屏状态变化
    handleFullscreenChange() {
      const isCurrentlyFullscreen = !!(
        document.fullscreenElement ||
        document.webkitFullscreenElement ||
        document.mozFullScreenElement ||
        document.msFullscreenElement
      );
      
      this.isFullscreen = isCurrentlyFullscreen;
      console.log('全屏状态变化:', this.isFullscreen);
      
      // 全屏状态变化时调整视频尺寸
      if (this.isFullscreen) {
        this.$nextTick(() => {
          this.adjustVideoForFullscreen();
        });
      } else {
        this.$nextTick(() => {
          this.resetVideoSize();
        });
      }
    },
    
    // 调整视频为全屏尺寸
    adjustVideoForFullscreen() {
      const videoElement = document.getElementById('publisher_video');
      if (videoElement) {
        videoElement.style.width = '100vw';
        videoElement.style.height = '100vh';
        videoElement.style.objectFit = 'cover';
        videoElement.style.position = 'fixed';
        videoElement.style.top = '0';
        videoElement.style.left = '0';
        videoElement.style.zIndex = '999';
      }
    },
    
    // 重置视频尺寸
    resetVideoSize() {
      const videoElement = document.getElementById('publisher_video');
      if (videoElement) {
        videoElement.style.width = '100%';
        videoElement.style.height = '300px';
        videoElement.style.objectFit = 'contain';
        videoElement.style.position = 'relative';
        videoElement.style.top = 'auto';
        videoElement.style.left = 'auto';
        videoElement.style.zIndex = 'auto';
      }
    },
    
    // 打开礼物面板
    openGiftPanel() {
      console.log('打开礼物面板，全屏状态:', this.isFullscreen);
      this.showGiftPanel = true;
    },
    
    // 关闭礼物面板
    closeGiftPanel() {
      this.showGiftPanel = false;
    },
    
    // 处理发送礼物
    handleSendGift(giftData) {
      console.log('发送礼物:', giftData);
      
      // 将礼物作为弹幕类型发送
      const giftContent = `🎁 送出了 ${giftData.name} ${giftData.icon}`;
      
      // 获取当前用户信息
      const currentUser = this.getCurrentUserInfo();
      
      // 通过WebSocket发送礼物信息（作为弹幕类型）
      if (this.websocket && this.websocketConnected) {
        const giftMessage = {
          type: 'danmaku',
          content: giftContent,
          user: currentUser.userName,
          toUserid: currentUser.userId,
          timestamp: Date.now(),
          // 添加礼物相关信息
          giftId: giftData.id,
          giftName: giftData.name,
          giftIcon: giftData.icon,
          giftPrice: giftData.price,
          giftCategory: giftData.category,
          isGift: true // 标记为礼物消息
        };
        
        this.websocket.send(JSON.stringify(giftMessage));
        console.log('礼物已通过WebSocket发送:', giftMessage);
        
        // 本地显示礼物动画
        this.showGiftAnimation(giftData, currentUser.userName);
      } else {
        // WebSocket不可用时，本地显示
        this.showGiftAnimation(giftData, currentUser.userName);
        console.log('礼物已本地发送:', giftData);
      }
    },
    
    // 显示礼物动画
    showGiftAnimation(giftData, user) {
      console.log('显示礼物动画:', giftData, '用户:', user, '全屏状态:', this.isFullscreen);
      
      const giftAnimation = {
        id: Date.now() + Math.random(),
        icon: giftData.icon,
        name: giftData.name,
        user: user,
        timestamp: Date.now(),
        price: giftData.price || 0,
        category: giftData.category || 'unknown'
      };
      
      this.giftAnimations.push(giftAnimation);
      
      // 根据礼物价格和类型添加不同特效
      this.addSpecialEffects(giftData, user);
      
      // 限制动画数量，避免过多影响性能
      if (this.giftAnimations.length > 10) {
        this.giftAnimations.shift();
      }
    },
    
    // 添加特殊特效
    addSpecialEffects(giftData, user) {
      const price = giftData.price || 0;
      
      // 根据价格添加不同特效
      if (price >= 200) {
        // 神话级礼物：凤凰 + 神龙 + 闪电 + 星空
        this.addPhoenixEffect(giftData);
        this.addDragonEffect(giftData);
        this.addLightningEffect(giftData);
        this.addStarEffect(giftData);
        this.addParticleEffect(giftData, 30);
      } else if (price >= 150) {
        // 传说级礼物：神龙 + 闪电 + 星空
        this.addDragonEffect(giftData);
        this.addLightningEffect(giftData);
        this.addStarEffect(giftData);
        this.addParticleEffect(giftData, 25);
      } else if (price >= 100) {
        // 豪华礼物：闪电 + 粒子 + 爆炸 + 彩虹
        this.addLightningEffect(giftData);
        this.addParticleEffect(giftData, 20);
        this.addExplosionEffect(giftData);
        this.addRainbowEffect(giftData);
      } else if (price >= 50) {
        // 高级礼物：星空 + 粒子 + 爆炸
        this.addStarEffect(giftData);
        this.addParticleEffect(giftData, 10);
        this.addExplosionEffect(giftData);
      } else if (price >= 20) {
        // 特殊礼物：粒子 + 彩虹
        this.addParticleEffect(giftData, 4);
        this.addRainbowEffect(giftData);
      } else {
        // 普通礼物：基础粒子
        this.addParticleEffect(giftData, 3);
      }
    },
    
    // 添加粒子特效
    addParticleEffect(giftData, customCount = null) {
      const particleCount = customCount || Math.min(8, Math.max(3, Math.floor((giftData.price || 1) / 5)));
      
      for (let i = 0; i < particleCount; i++) {
        const particle = {
          id: Date.now() + Math.random() + i,
          icon: this.getRandomParticleIcon(),
          x: Math.random() * 100,
          y: Math.random() * 100,
          delay: i * 0.1
        };
        
        this.particleEffects.push(particle);
      }
      
      // 限制粒子数量
      if (this.particleEffects.length > 50) {
        this.particleEffects.splice(0, 10);
      }
    },
    
    // 添加爆炸特效
    addExplosionEffect(giftData) {
      const explosion = {
        id: Date.now() + Math.random(),
        x: Math.random() * 80 + 10,
        y: Math.random() * 60 + 20,
        size: Math.min(3, Math.max(1, (giftData.price || 1) / 50))
      };
      
      this.explosionEffects.push(explosion);
      
      // 限制爆炸数量
      if (this.explosionEffects.length > 5) {
        this.explosionEffects.shift();
      }
    },
    
    // 添加彩虹特效
    addRainbowEffect(giftData) {
      const rainbow = {
        id: Date.now() + Math.random(),
        x: Math.random() * 70 + 15,
        y: Math.random() * 40 + 30,
        size: Math.min(2, Math.max(0.5, (giftData.price || 1) / 100))
      };
      
      this.rainbowEffects.push(rainbow);
      
      // 限制彩虹数量
      if (this.rainbowEffects.length > 3) {
        this.rainbowEffects.shift();
      }
    },
    
    // 获取随机粒子图标
    getRandomParticleIcon() {
      const particles = ['✨', '⭐', '💫', '🌟', '💎', '🔮', '💖', '💝'];
      return particles[Math.floor(Math.random() * particles.length)];
    },
    
    // 获取礼物动画样式
    getGiftAnimationStyle(gift, index) {
      return {
        top: Math.floor(Math.random() * 60) + 20 + '%', // 随机高度
        left: Math.floor(Math.random() * 80) + 10 + '%', // 随机水平位置
        animationDelay: index * 0.2 + 's' // 错开动画时间
      };
    },
    
    // 获取礼物动画类名
    getGiftAnimationClass(gift) {
      const price = gift.price || 0;
      if (price >= 100) return 'luxury-gift';
      if (price >= 50) return 'premium-gift';
      if (price >= 20) return 'special-gift';
      return 'normal-gift';
    },
    
    // 获取粒子样式
    getParticleStyle(particle) {
      return {
        left: particle.x + '%',
        top: particle.y + '%',
        animationDelay: particle.delay + 's'
      };
    },
    
    // 获取爆炸样式
    getExplosionStyle(explosion) {
      return {
        left: explosion.x + '%',
        top: explosion.y + '%',
        transform: `scale(${explosion.size})`
      };
    },
    
    // 获取彩虹样式
    getRainbowStyle(rainbow) {
      return {
        left: rainbow.x + '%',
        top: rainbow.y + '%',
        transform: `scale(${rainbow.size})`
      };
    },
    
    // 获取闪电样式
    getLightningStyle(lightning) {
      return {
        left: lightning.x + 'px',
        top: lightning.y + 'px',
        opacity: lightning.intensity
      };
    },
    
    // 获取神龙样式
    getDragonStyle(dragon) {
      return {
        left: dragon.x + 'px',
        top: dragon.y + 'px',
        transform: `scale(${dragon.size})`
      };
    },
    
    // 获取凤凰样式
    getPhoenixStyle(phoenix) {
      return {
        left: phoenix.x + 'px',
        top: phoenix.y + 'px',
        transform: `scale(${phoenix.size})`
      };
    },
    
    // 获取星空样式
    getStarStyle(star) {
      return {
        left: star.x + 'px',
        top: star.y + 'px',
        transform: `scale(${star.size})`,
        animationDuration: star.twinkle + 's'
      };
    },
    
    // 移除礼物动画
    removeGiftAnimation(index) {
      if (index >= 0 && index < this.giftAnimations.length) {
        this.giftAnimations.splice(index, 1);
      }
    },
    
    // 移除粒子特效
    removeParticleEffect(index) {
      if (index >= 0 && index < this.particleEffects.length) {
        this.particleEffects.splice(index, 1);
      }
    },
    
    // 移除爆炸特效
    removeExplosionEffect(index) {
      if (index >= 0 && index < this.explosionEffects.length) {
        this.explosionEffects.splice(index, 1);
      }
    },
    
    // 移除彩虹特效
    removeRainbowEffect(index) {
      if (index >= 0 && index < this.rainbowEffects.length) {
        this.rainbowEffects.splice(index, 1);
      }
    },
    
    // 添加闪电特效
    addLightningEffect(giftData) {
      const lightning = {
        id: Date.now() + Math.random(),
        x: Math.random() * (window.innerWidth - 200) + 100,
        y: Math.random() * (window.innerHeight - 200) + 100,
        intensity: Math.random() * 0.5 + 0.5
      };
      
      this.lightningEffects.push(lightning);
      
      // 限制特效数量
      if (this.lightningEffects.length > 5) {
        this.lightningEffects.shift();
      }
    },
    
    // 添加神龙特效
    addDragonEffect(giftData) {
      const dragon = {
        id: Date.now() + Math.random(),
        x: Math.random() * (window.innerWidth - 300) + 150,
        y: Math.random() * (window.innerHeight - 300) + 150,
        size: Math.random() * 0.5 + 0.8
      };
      
      this.dragonEffects.push(dragon);
      
      // 限制特效数量
      if (this.dragonEffects.length > 3) {
        this.dragonEffects.shift();
      }
    },
    
    // 添加凤凰特效
    addPhoenixEffect(giftData) {
      const phoenix = {
        id: Date.now() + Math.random(),
        x: Math.random() * (window.innerWidth - 400) + 200,
        y: Math.random() * (window.innerHeight - 400) + 200,
        size: Math.random() * 0.3 + 1.0
      };
      
      this.phoenixEffects.push(phoenix);
      
      // 限制特效数量
      if (this.phoenixEffects.length > 2) {
        this.phoenixEffects.shift();
      }
    },
    
    // 添加星空特效
    addStarEffect(giftData) {
      const starCount = Math.min(15, Math.max(5, Math.floor((giftData.price || 1) / 10)));
      
      for (let i = 0; i < starCount; i++) {
        const star = {
          id: Date.now() + Math.random() + i,
          x: Math.random() * window.innerWidth,
          y: Math.random() * window.innerHeight,
          size: Math.random() * 0.5 + 0.5,
          twinkle: Math.random() * 2 + 1
        };
        
        this.starEffects.push(star);
      }
      
      // 限制特效数量
      if (this.starEffects.length > 50) {
        this.starEffects.splice(0, this.starEffects.length - 50);
      }
    },
    
    // 移除闪电特效
    removeLightningEffect(index) {
      if (index >= 0 && index < this.lightningEffects.length) {
        this.lightningEffects.splice(index, 1);
      }
    },
    
    // 移除神龙特效
    removeDragonEffect(index) {
      if (index >= 0 && index < this.dragonEffects.length) {
        this.dragonEffects.splice(index, 1);
      }
    },
    
    // 移除凤凰特效
    removePhoenixEffect(index) {
      if (index >= 0 && index < this.phoenixEffects.length) {
        this.phoenixEffects.splice(index, 1);
      }
    },
    
    // 移除星空特效
    removeStarEffect(index) {
      if (index >= 0 && index < this.starEffects.length) {
        this.starEffects.splice(index, 1);
      }
    },
    
    // 从消息内容解析礼物信息
    parseAndShowGiftFromContent(content, user) {
      try {
        // 解析格式: "🎁 送出了 鲜花 🌹"
        const giftMatch = content.match(/🎁 送出了 (.+?) (.+)/);
        if (giftMatch) {
          const giftName = giftMatch[1];
          const giftIcon = giftMatch[2];
          
          // 创建礼物数据对象
          const giftData = {
            id: Date.now(), // 临时ID
            name: giftName,
            icon: giftIcon,
            price: 0, // 未知价格
            category: 'unknown'
          };
          
          console.log('解析出的礼物数据:', giftData);
          this.showGiftAnimation(giftData, user);
        }
      } catch (error) {
        console.error('解析礼物内容失败:', error);
      }
    }
  },
  
  beforeDestroy() {
    // 页面销毁前清理所有资源
    this.leaveRoom();
    
    // 关闭WebSocket连接
    if (this.websocket) {
      this.websocket.close();
      console.log('WebSocket连接已关闭');
    }
    
    // 清理签到定时器
    if (this.attendanceTimer) {
      clearInterval(this.attendanceTimer);
      this.attendanceTimer = null;
    }
  },
  

}
</script>

<style scoped>
.container {
  display: flex;
  flex-direction: column;
  height: 130vh;
  background: linear-gradient(135deg, #0f0f23 0%, #1a1a2e 50%, #16213e 100%);
  color: #ffffff;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

.header {
  text-align: center;
  padding: 20px 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
  backdrop-filter: blur(20px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.title {
  font-size: 24px;
  font-weight: 700;
  color: #ffffff;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
  letter-spacing: 1px;
}

.main-content {
  flex: 1;
  display: flex;
  flex-direction: row;
  background: transparent;
  overflow: hidden;
  gap: 15px;
  padding: 15px;
}

.main-video-section, .audience-video-section, .danmaku-list-section {
  display: flex;
  flex-direction: column;
  height: 100%;
  border-radius: 16px;
  overflow: hidden;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.main-video-section {
  flex: 5;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
}

.audience-video-section {
  flex: 1.5;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%);
}

.danmaku-list-section {
  flex: 1.5;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.08) 0%, rgba(255, 255, 255, 0.03) 100%);
}

.section-title {
  color: #ffffff;
  font-size: 16px;
  font-weight: 700;
  padding: 12px 20px;
  text-align: center;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%);
  border-radius: 12px 12px 0 0;
  margin: 0;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  letter-spacing: 0.5px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.main-video-wrapper, .audience-video-wrapper, .danmaku-list-wrapper {
  flex: 1;
  overflow: hidden;
  position: relative;
  padding: 15px;
}

.main-video-wrapper {
  height: calc(100% - 50px);
}

.audience-video-wrapper {
  overflow-y: auto;
  padding: 10px;
}

.danmaku-list-wrapper {
  overflow-y: auto;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.2) 0%, rgba(0, 0, 0, 0.1) 100%);
  border-radius: 12px;
  padding: 12px;
  margin: 8px;
}

.main-video-container, .remote-video-container {
  position: relative;
  width: 100%;
  height: 100%;
  margin-bottom: 10px;
  border: 2px solid rgba(255, 255, 255, 0.2);
  border-radius: 12px;
  overflow: hidden;
  background: linear-gradient(135deg, #000000 0%, #1a1a1a 100%);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
  transition: all 0.3s ease;
}

.main-video-container:hover, .remote-video-container:hover {
  border-color: rgba(0, 122, 255, 0.5);
  box-shadow: 0 12px 40px rgba(0, 122, 255, 0.2);
  
}

.remote-video-container {
  height: 230px;
  margin-bottom: 15px;
}

.video-player {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, #000000 0%, #1a1a1a 100%);
  border-radius: 10px;
  object-fit: cover;
}

.video-label {
  position: absolute;
  top: 8px;
  left: 8px;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 100%);
  color: white;
  padding: 6px 12px;
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.2);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.8);
  letter-spacing: 0.5px;
}

.local-label {
  background: linear-gradient(135deg, rgba(0, 122, 255, 0.9) 0%, rgba(0, 122, 255, 0.7) 100%);
  box-shadow: 0 4px 15px rgba(0, 122, 255, 0.3);
}

.remote-label {
  background: linear-gradient(135deg, rgba(255, 149, 0, 0.9) 0%, rgba(255, 149, 0, 0.7) 100%);
  box-shadow: 0 4px 15px rgba(255, 149, 0, 0.3);
}

.placeholder, .scroll-placeholder {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 100%);
  border-radius: 12px;
  backdrop-filter: blur(10px);
  font-size: 16px;
  font-weight: 500;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.8);
}

.scroll-placeholder {
  position: relative;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.1) 100%);
  border-radius: 12px;
  margin: 10px;
  min-height: 100px;
}

.room-info {
  display: flex;
  flex-direction: row;
  gap: 10px;
  margin: 10px 15px;
  padding: 12px 16px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
  border-radius: 12px;
  backdrop-filter: blur(20px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.input-field {
  flex: 1;
  height: 36px;
  padding: 0 15px;
  border: 2px solid rgba(255, 255, 255, 0.2);
  border-radius: 18px;
  font-size: 13px;
  font-weight: 500;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.2) 100%);
  color: #ffffff;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
}

.input-field:focus {
  outline: none;
  border-color: #007AFF;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%);
  box-shadow: 0 0 20px rgba(0, 122, 255, 0.3);
}

.input-field::placeholder {
  color: rgba(255, 255, 255, 0.6);
}

.status-info {
  text-align: center;
  color: rgba(255, 255, 255, 0.8);
  font-size: 13px;
  font-weight: 500;
  padding: 10px 15px;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.1) 100%);
  border-radius: 10px;
  margin: 10px 15px;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.audience-placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
  border: 2px dashed rgba(255, 255, 255, 0.3);
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 150px;
  backdrop-filter: blur(10px);
  transition: all 0.3s ease;
}

.audience-placeholder:hover {
  border-color: rgba(255, 255, 255, 0.5);
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%);
}

.placeholder-icon {
  font-size: 40px;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: 10px;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}

.placeholder-text {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.7);
  text-align: center;
  font-weight: 500;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

/* 弹幕历史列表样式 */
.danmaku-history-item {
  display: flex;
  align-items: flex-start;
  padding: 10px 14px;
  margin-bottom: 8px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
  border-radius: 10px;
  border-left: 3px solid #007AFF;
  backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.1);
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}

.danmaku-history-item:hover {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.2);
}

.danmaku-history-user {
  color: #007AFF;
  font-weight: 700;
  margin-right: 8px;
  font-size: 13px;
  white-space: nowrap;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.danmaku-history-content {
  flex: 1;
  color: #ffffff;
  font-size: 13px;
  margin-right: 8px;
  word-break: break-all;
  line-height: 1.4;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.danmaku-history-time {
  color: rgba(255, 255, 255, 0.6);
  font-size: 11px;
  white-space: nowrap;
  font-weight: 500;
}

.danmaku-placeholder {
  display: flex;
  justify-content: center;
  align-items: center;
  height: 150px;
  color: rgba(255, 255, 255, 0.6);
  font-size: 14px;
  font-weight: 500;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

/* 控制按钮样式 */
.controls {
  display: flex;
  justify-content: space-around;
  margin: 10px 15px;
  gap: 10px;
  padding: 0;
}

.control-btn {
  flex: 1;
  height: 40px;
  font-size: 14px;
  border-radius: 20px;
  border: none;
  color: white;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  letter-spacing: 0.5px;
}

.control-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
}

.control-btn:active {
  transform: translateY(0);
}

.control-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
  transform: none;
}

.join-btn {
  background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
}

.join-btn:hover:not(:disabled) {
  background: linear-gradient(135deg, #0056CC 0%, #004499 100%);
}

.leave-btn {
  background: linear-gradient(135deg, #FF3B30 0%, #CC2E24 100%);
}

.leave-btn:hover:not(:disabled) {
  background: linear-gradient(135deg, #CC2E24 0%, #99221A 100%);
}

/* 弹幕输入区域样式 */
.danmaku-input-section {
  padding: 15px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
  backdrop-filter: blur(20px);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 -4px 20px rgba(0, 0, 0, 0.2);
}

.input-area {
  display: flex;
  align-items: center;
  gap: 12px;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.3) 0%, rgba(0, 0, 0, 0.1) 100%);
  padding: 12px 16px;
  border-radius: 20px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

.danmaku-switch {
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  padding: 6px 10px;
  border-radius: 16px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.05) 100%);
  transition: all 0.3s ease;
}

.danmaku-switch:hover {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.15) 0%, rgba(255, 255, 255, 0.08) 100%);
}

.switch-text {
  color: #fff;
  font-size: 13px;
  font-weight: 600;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.switch-icon {
  width: 20px;
  height: 10px;
  background: linear-gradient(135deg, #666 0%, #444 100%);
  border-radius: 5px;
  position: relative;
  transition: all 0.3s ease;
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.3);
}

.switch-icon.active {
  background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
  box-shadow: 0 4px 15px rgba(0, 122, 255, 0.3);
}

.switch-icon.active::after {
  content: '';
  position: absolute;
  right: 2px;
  top: 2px;
  width: 8px;
  height: 8px;
  background: white;
  border-radius: 50%;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
}

.message-input {
  flex: 1;
  height: 36px;
  padding: 0 16px;
  border: 2px solid rgba(255, 255, 255, 0.2);
  border-radius: 18px;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.4) 0%, rgba(0, 0, 0, 0.2) 100%);
  color: #fff;
  font-size: 13px;
  font-weight: 500;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
}

.message-input:focus {
  outline: none;
  border-color: #007AFF;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.6) 0%, rgba(0, 0, 0, 0.3) 100%);
  box-shadow: 0 0 20px rgba(0, 122, 255, 0.3);
}

.message-input::placeholder {
  color: rgba(255, 255, 255, 0.6);
}

.send-btn {
  height: 36px;
  padding: 0 16px;
  background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
  color: white;
  border: none;
  border-radius: 18px;
  font-size: 13px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(0, 122, 255, 0.3);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.send-btn:hover {
  background: linear-gradient(135deg, #0056CC 0%, #004499 100%);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 122, 255, 0.4);
}

.gift-btn {
  height: 36px;
  padding: 0 12px;
  background: linear-gradient(135deg, #FF6B6B 0%, #FF5252 100%);
  color: white;
  border: none;
  border-radius: 18px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  min-width: 50px;
}

.gift-btn:hover {
  background: linear-gradient(135deg, #FF5252 0%, #FF1744 100%);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
}

/* 全屏弹幕输入样式 */
.fullscreen-danmaku-input {
  position: fixed;
  bottom: 30px;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1200;
  background: transparent;
  padding: 15px 25px;
  border-radius: 30px;
  display: flex;
  align-items: center;
  gap: 15px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
}

.fullscreen-input-area {
  display: flex;
  align-items: center;
  gap: 15px;
}

.danmaku-toggle-btn {
  padding: 8px 16px;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.2) 0%, rgba(255, 255, 255, 0.1) 100%);
  color: white;
  border: 1px solid rgba(255, 255, 255, 0.3);
  border-radius: 20px;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.danmaku-toggle-btn.active {
  background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
  border-color: #007AFF;
  box-shadow: 0 4px 15px rgba(0, 122, 255, 0.3);
}

.danmaku-toggle-btn:hover {
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.3) 0%, rgba(255, 255, 255, 0.15) 100%);
}

.fullscreen-message-input {
  width: 250px;
  height: 40px;
  padding: 0 20px;
  background: transparent;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 20px;
  color: white;
  font-size: 14px;
  font-weight: 500;
  transition: all 0.3s ease;
}

.fullscreen-message-input:focus {
  outline: none;
  border-color: #007AFF;
  background: transparent;
  box-shadow: 0 0 20px rgba(0, 122, 255, 0.3);
}

.fullscreen-message-input::placeholder {
  color: rgba(255, 255, 255, 0.6);
}

.fullscreen-send-btn {
  height: 40px;
  padding: 0 20px;
  background: linear-gradient(135deg, #007AFF 0%, #0056CC 100%);
  color: white;
  border: none;
  border-radius: 20px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(0, 122, 255, 0.3);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}

.fullscreen-send-btn:hover {
  background: linear-gradient(135deg, #0056CC 0%, #004499 100%);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 122, 255, 0.4);
}

.fullscreen-gift-btn {
  height: 40px;
  padding: 0 16px;
  background: linear-gradient(135deg, #FF6B6B 0%, #FF5252 100%);
  color: white;
  border: none;
  border-radius: 20px;
  font-size: 16px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 15px rgba(255, 107, 107, 0.3);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  min-width: 60px;
}

.fullscreen-gift-btn:hover {
  background: linear-gradient(135deg, #FF5252 0%, #FF1744 100%);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(255, 107, 107, 0.4);
}

/* 全屏控制按钮样式 */
.fullscreen-controls {
  position: absolute;
  top: 15px;
  right: 15px;
  z-index: 100;
}

.fullscreen-btn {
  padding: 10px 20px;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 100%);
  color: white;
  border: 2px solid rgba(255, 255, 255, 0.3);
  border-radius: 25px;
  font-size: 14px;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.3s ease;
  backdrop-filter: blur(10px);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
  letter-spacing: 0.5px;
}

.fullscreen-btn:hover {
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.9) 0%, rgba(0, 0, 0, 0.7) 100%);
  border-color: rgba(255, 255, 255, 0.5);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(0, 0, 0, 0.4);
}

/* 弹幕滚动样式 */
.danmaku-container {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 50;
}

.danmaku-scroll-item {
  position: absolute;
  white-space: nowrap;
  color: #ffffff;
  font-size: 18px;
  font-weight: 700;
  padding: 8px 16px;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.8) 0%, rgba(0, 0, 0, 0.6) 100%);
  border-radius: 20px;
  backdrop-filter: blur(10px);
  text-shadow: 2px 2px 8px rgba(0, 0, 0, 0.9);
  animation: danmaku-scroll 4s linear;
  animation-fill-mode: forwards;
  z-index: 100;
  pointer-events: none;
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
  letter-spacing: 0.5px;
}

@keyframes danmaku-scroll {
  0% {
    transform: translateX(100vw);
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  95% {
    opacity: 1;
  }
  100% {
    transform: translateX(-100vw);
    opacity: 0;
    visibility: hidden;
  }
}

/* 全屏时的弹幕容器 */
.danmaku-container.fullscreen-danmaku {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1000;
}

/* 签到弹窗样式 */
.attendance-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
}

.attendance-modal {
  background-color: white;
  border-radius: 10px;
  padding: 20px;
  max-width: 500px;
  width: 90%;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
}

.attendance-header {
  text-align: center;
  margin-bottom: 15px;
}

.attendance-title {
  font-size: 18px;
  font-weight: bold;
  color: #333;
  margin-bottom: 5px;
}

.attendance-countdown {
  font-size: 14px;
  color: #666;
}

.attendance-content {
  text-align: center;
  margin-bottom: 20px;
}

.attendance-message {
  font-size: 16px;
  color: #333;
  line-height: 1.5;
}

.attendance-actions {
  display: flex;
  justify-content: center;
}

.attendance-btn {
  padding: 10px 20px;
  border: none;
  border-radius: 5px;
  font-size: 16px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.confirm-btn {
  background-color: #007AFF;
  color: white;
}

.confirm-btn:hover {
  background-color: #0056CC;
}

.confirm-btn:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

/* 摄像头相关样式 */
.camera-section {
  margin: 20px 0;
  text-align: center;
}

.camera-container {
  position: relative;
  display: inline-block;
  margin-bottom: 15px;
  border-radius: 10px;
  overflow: hidden;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
}

.attendance-video {
  width: 320px;
  height: 240px;
  background-color: #000;
  object-fit: cover;
  display: block;
}

.attendance-canvas {
  position: absolute;
  top: 0;
  left: 0;
}

.camera-controls {
  display: flex;
  justify-content: center;
  gap: 10px;
  margin-bottom: 15px;
}

.camera-btn {
  padding: 8px 16px;
  border: none;
  border-radius: 5px;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
}

.start-camera-btn {
  background-color: #28a745;
  color: white;
}

.start-camera-btn:hover {
  background-color: #218838;
}

.capture-btn {
  background-color: #ffc107;
  color: #212529;
}

.capture-btn:hover {
  background-color: #e0a800;
}

.stop-camera-btn {
  background-color: #dc3545;
  color: white;
}

.stop-camera-btn:hover {
  background-color: #c82333;
}

.photo-preview {
  margin-top: 15px;
  padding: 10px;
  background-color: #f8f9fa;
  border-radius: 8px;
  border: 2px solid #28a745;
}

.preview-image {
  max-width: 200px;
  max-height: 150px;
  border-radius: 5px;
  margin-bottom: 8px;
}

.preview-text {
  font-size: 14px;
  color: #28a745;
  font-weight: bold;
  margin: 0;
}

.join-btn {
  background-color: #007aff;
}

.join-btn:disabled {
  background-color: #ccc;
  color: #666;
}

.leave-btn {
  background-color: #ff3b30;
}

.leave-btn:disabled {
  background-color: #ccc;
  color: #666;
}

/* 弹幕发送区域样式 */
.danmaku-input-section {
  padding: 20rpx;
  background-color: #2a2a2a;
  border-top: 1rpx solid #333;
}

.danmaku-input-section .input-area {
  display: flex;
  align-items: center;
  gap: 20rpx;
}

.danmaku-switch {
  display: flex;
  align-items: center;
  gap: 10rpx;
}

.switch-text {
  color: #ffffff;
  font-size: 28rpx;
}

.switch-icon {
  width: 40rpx;
  height: 20rpx;
  background-color: #666;
  border-radius: 10rpx;
  position: relative;
  transition: background-color 0.3s;
}

.switch-icon.active {
  background-color: #007aff;
}

.switch-icon::after {
  content: '';
  position: absolute;
  top: 2rpx;
  left: 2rpx;
  width: 16rpx;
  height: 16rpx;
  background-color: #ffffff;
  border-radius: 50%;
  transition: transform 0.3s;
}

.switch-icon.active::after {
  transform: translateX(20rpx);
}

.danmaku-input-section .message-input {
  flex: 1;
  height: 60rpx;
  background-color: #3a3a3a;
  border-radius: 30rpx;
  padding: 0 20rpx;
  color: #ffffff;
  font-size: 28rpx;
  border: 1rpx solid #333;
}

.danmaku-input-section .message-input::placeholder {
  color: #999;
}

.danmaku-input-section .send-btn {
  height: 60rpx;
  padding: 0 30rpx;
  background-color: #007aff;
  color: white;
  border: none;
  border-radius: 30rpx;
  font-size: 28rpx;
  font-weight: bold;
}

/* 全屏时的弹幕输入区域 */
.danmaku-input-section.fullscreen-input {
  position: fixed;
  bottom: 0;
  left: 0;
  right: 0;
  z-index: 1001;
  background-color: rgba(42, 42, 42, 0.95);
  backdrop-filter: blur(10px);
  padding: 20rpx;
  border-top: 1rpx solid rgba(255, 255, 255, 0.2);
}

/* 全屏时确保输入框可见 */
.danmaku-input-section.fullscreen-input .input-area {
  max-width: 800rpx;
  margin: 0 auto;
}

.danmaku-input-section.fullscreen-input .message-input {
  background-color: rgba(58, 58, 58, 0.9);
  border: 1rpx solid rgba(255, 255, 255, 0.3);
}

.danmaku-input-section.fullscreen-input .send-btn {
  background-color: #007aff;
  border: 1rpx solid rgba(255, 255, 255, 0.2);
}

/* 全屏弹幕输入区域 */

.fullscreen-input-area {
  display: flex;
  align-items: center;
  gap: 15rpx;
}

.fullscreen-message-input {
  width: 450rpx;
  height: 70rpx;
  background-color: rgba(255, 255, 255, 0.15);
  border: 2rpx solid rgba(255, 255, 255, 0.4);
  border-radius: 35rpx;
  padding: 0 25rpx;
  color: #ffffff;
  font-size: 30rpx;
  transition: all 0.3s ease;
}

.fullscreen-message-input:focus {
  border-color: #007aff;
  background-color: rgba(255, 255, 255, 0.2);
  outline: none;
}

.fullscreen-message-input::placeholder {
  color: rgba(255, 255, 255, 0.7);
  font-size: 28rpx;
}

.fullscreen-send-btn {
  height: 70rpx;
  padding: 0 35rpx;
  background-color: #007aff;
  color: white;
  border: 2rpx solid #007aff;
  border-radius: 35rpx;
  font-size: 30rpx;
  font-weight: bold;
  min-width: 120rpx;
  cursor: pointer;
  transition: all 0.3s ease;
}

.fullscreen-send-btn:hover {
  background-color: #0056b3;
  border-color: #0056b3;
  transform: scale(1.05);
}

.fullscreen-send-btn:active {
  transform: scale(0.95);
}

/* 全屏控制按钮 */
.fullscreen-controls {
  position: absolute;
  top: 10rpx;
  right: 10rpx;
  z-index: 1003;
}

/* 全屏时的控制按钮 */
.main-video-wrapper:fullscreen .fullscreen-controls,
.main-video-wrapper:-webkit-full-screen .fullscreen-controls,
.main-video-wrapper:-moz-full-screen .fullscreen-controls,
.main-video-wrapper:-ms-fullscreen .fullscreen-controls {
  position: fixed;
  top: 20rpx;
  right: 20rpx;
  z-index: 1003;
}

.fullscreen-btn {
  background-color: rgba(0, 0, 0, 0.7);
  color: white;
  border: 2rpx solid rgba(255, 255, 255, 0.5);
  border-radius: 8rpx;
  padding: 15rpx 25rpx;
  font-size: 28rpx;
  font-weight: bold;
  backdrop-filter: blur(10px);
  cursor: pointer;
  transition: all 0.3s ease;
  min-width: 120rpx;
  text-align: center;
}

.fullscreen-btn:hover {
  background-color: rgba(0, 0, 0, 0.9);
  border-color: rgba(255, 255, 255, 0.8);
  transform: scale(1.05);
}

.fullscreen-btn:active {
  transform: scale(0.95);
}

/* 全屏弹幕输入区域 */

.fullscreen-message-input {
  width: 400rpx;
  height: 60rpx;
  background-color: rgba(255, 255, 255, 0.15);
  border: 2rpx solid rgba(255, 255, 255, 0.4);
  border-radius: 30rpx;
  padding: 0 20rpx;
  color: #ffffff;
  font-size: 28rpx;
  outline: none;
}

.fullscreen-message-input:focus {
  border-color: #007aff;
  background-color: rgba(255, 255, 255, 0.25);
}

.fullscreen-message-input::placeholder {
  color: rgba(255, 255, 255, 0.6);
}

.fullscreen-send-btn {
  height: 60rpx;
  padding: 0 30rpx;
  background-color: rgba(0, 122, 255, 0.8);
  color: white;
  border: 2rpx solid rgba(0, 122, 255, 0.8);
  border-radius: 30rpx;
  font-size: 28rpx;
  font-weight: bold;
  cursor: pointer;
  transition: all 0.3s ease;
}

.fullscreen-send-btn:hover {
  background-color: rgba(0, 91, 179, 0.9);
  border-color: rgba(0, 91, 179, 0.9);
}

.fullscreen-send-btn:active {
  transform: scale(0.95);
}

/* 全屏时的视频容器 */
.main-video-wrapper:fullscreen {
  background-color: #000;
  width: 100vw !important;
  height: 100vh !important;
  display: flex;
  align-items: center;
  justify-content: center;
}

.main-video-wrapper:-webkit-full-screen {
  background-color: #000;
  width: 100vw !important;
  height: 100vh !important;
  display: flex;
  align-items: center;
  justify-content: center;
}

.main-video-wrapper:-moz-full-screen {
  background-color: #000;
  width: 100vw !important;
  height: 100vh !important;
  display: flex;
  align-items: center;
  justify-content: center;
}

.main-video-wrapper:-ms-fullscreen {
  background-color: #000;
  width: 100vw !important;
  height: 100vh !important;
  display: flex;
  align-items: center;
  justify-content: center;
}

/* 全屏时的视频元素 */
.main-video-wrapper:fullscreen .main-video-container {
  width: 100vw !important;
  height: 100vh !important;
  max-width: 100vw !important;
  max-height: 100vh !important;
}

.main-video-wrapper:-webkit-full-screen .main-video-container {
  width: 100vw !important;
  height: 100vh !important;
  max-width: 100vw !important;
  max-height: 100vh !important;
}

.main-video-wrapper:-moz-full-screen .main-video-container {
  width: 100vw !important;
  height: 100vh !important;
  max-width: 100vw !important;
  max-height: 100vh !important;
}

.main-video-wrapper:-ms-fullscreen .main-video-container {
  width: 100vw !important;
  height: 100vh !important;
  max-width: 100vw !important;
  max-height: 100vh !important;
}

/* 全屏时的视频播放器 */
.main-video-wrapper:fullscreen .video-player {
  width: 100vw !important;
  height: 100vh !important;
  object-fit: cover !important;
}

.main-video-wrapper:-webkit-full-screen .video-player {
  width: 100vw !important;
  height: 100vh !important;
  object-fit: cover !important;
}

.main-video-wrapper:-moz-full-screen .video-player {
  width: 100vw !important;
  height: 100vh !important;
  object-fit: cover !important;
}

.main-video-wrapper:-ms-fullscreen .video-player {
  width: 100vw !important;
  height: 100vh !important;
  object-fit: cover !important;
}

/* 弹幕滚动样式 - 显示在主画面区域 */
.danmaku-container {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 50;
}

/* 全屏时的弹幕容器 */
.danmaku-container.fullscreen-danmaku {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1000;
}

.danmaku-scroll-item {
  position: absolute;
  white-space: nowrap;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5);
  animation: danmaku 4s linear;
  animation-fill-mode: forwards;
  z-index: 100;
  pointer-events: none;
  color: #ffffff;
  font-size: 16px;
  font-weight: bold;
}

/* 弹幕滚动动画 */
@keyframes danmaku {
  0% {
    transform: translateX(100vw);
    opacity: 0;
  }
  5% {
    opacity: 1;
  }
  95% {
    opacity: 1;
  }
  100% {
    transform: translateX(-100vw);
    opacity: 0;
    visibility: hidden;
  }
}

/* 礼物动画容器样式 */
.gift-animation-container {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  pointer-events: none;
  overflow: hidden;
  z-index: 60;
}

.gift-animation-container.fullscreen-gift {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100vw;
  height: 100vh;
  z-index: 1500;
}

/* 基础礼物动画 */
.gift-animation {
  position: absolute;
  pointer-events: none;
  z-index: 100;
}

/* 不同等级的礼物动画时间 */
.normal-gift {
  animation: gift-float-normal 2s ease-out forwards;
}

.special-gift {
  animation: gift-float-special 2.5s ease-out forwards;
}

.premium-gift {
  animation: gift-float-premium 3s ease-out forwards;
}

.luxury-gift {
  animation: gift-float-luxury 3.5s ease-out forwards;
}

.gift-animation-content {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 20px;
  border-radius: 25px;
  box-shadow: 0 8px 25px rgba(255, 215, 0, 0.4);
  border: 2px solid rgba(255, 255, 255, 0.3);
  backdrop-filter: blur(10px);
  position: relative;
  overflow: hidden;
}

/* 添加光晕效果 */
.gift-animation-content::before {
  content: '';
  position: absolute;
  top: -2px;
  left: -2px;
  right: -2px;
  bottom: -2px;
  background: linear-gradient(45deg, transparent, rgba(255, 255, 255, 0.3), transparent);
  border-radius: 27px;
  z-index: -1;
  animation: shimmer 2s ease-in-out infinite;
}

/* 添加内部光效 */
.gift-animation-content::after {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
  animation: light-sweep 3s ease-in-out infinite;
}

/* 不同等级的礼物样式 */
.normal-gift .gift-animation-content {
  background: linear-gradient(135deg, rgba(255, 215, 0, 0.9) 0%, rgba(255, 193, 7, 0.9) 100%);
  box-shadow: 0 8px 25px rgba(255, 215, 0, 0.4);
}

.special-gift .gift-animation-content {
  background: linear-gradient(135deg, rgba(138, 43, 226, 0.9) 0%, rgba(75, 0, 130, 0.9) 100%);
  box-shadow: 0 8px 25px rgba(138, 43, 226, 0.4), 0 0 20px rgba(138, 43, 226, 0.3);
  border: 2px solid rgba(138, 43, 226, 0.6);
  animation: special-pulse 2s ease-in-out infinite;
}

.premium-gift .gift-animation-content {
  background: linear-gradient(135deg, rgba(255, 20, 147, 0.9) 0%, rgba(255, 105, 180, 0.9) 100%);
  box-shadow: 0 8px 25px rgba(255, 20, 147, 0.4), 0 0 30px rgba(255, 20, 147, 0.4);
  border: 2px solid rgba(255, 20, 147, 0.6);
  animation: premium-glow 1.5s ease-in-out infinite alternate;
}

.luxury-gift .gift-animation-content {
  background: linear-gradient(135deg, rgba(255, 215, 0, 0.9) 0%, rgba(255, 140, 0, 0.9) 25%, rgba(255, 69, 0, 0.9) 50%, rgba(255, 20, 147, 0.9) 75%, rgba(138, 43, 226, 0.9) 100%);
  box-shadow: 0 8px 25px rgba(255, 215, 0, 0.6), 0 0 40px rgba(255, 215, 0, 0.4), 0 0 60px rgba(255, 20, 147, 0.3);
  border: 3px solid rgba(255, 215, 0, 0.8);
  animation: luxury-glow 1s ease-in-out infinite alternate;
  position: relative;
}

/* 豪华礼物的额外特效 */
.luxury-gift .gift-animation-content::before {
  background: linear-gradient(45deg, 
    rgba(255, 215, 0, 0.5), 
    rgba(255, 140, 0, 0.5), 
    rgba(255, 69, 0, 0.5), 
    rgba(255, 20, 147, 0.5), 
    rgba(138, 43, 226, 0.5)
  );
  animation: luxury-shimmer 1.5s ease-in-out infinite;
}

.gift-animation .gift-icon {
  font-size: 24px;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

/* 不同等级的图标动画 */
.normal-gift .gift-icon {
  animation: icon-bounce 1s ease-in-out infinite alternate;
}

.special-gift .gift-icon {
  animation: icon-rotate 2s linear infinite;
  text-shadow: 0 0 15px rgba(138, 43, 226, 0.8);
}

.premium-gift .gift-icon {
  animation: icon-pulse 1.5s ease-in-out infinite;
  text-shadow: 0 0 20px rgba(255, 20, 147, 0.8);
}

.luxury-gift .gift-icon {
  animation: icon-luxury 2s ease-in-out infinite;
  text-shadow: 0 0 25px rgba(255, 215, 0, 0.8), 0 0 35px rgba(255, 20, 147, 0.6);
}

.gift-animation .gift-text {
  color: #ffffff;
  font-size: 16px;
  font-weight: 700;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
}

/* 粒子特效 */
.particle-effect {
  position: absolute;
  pointer-events: none;
  z-index: 80;
}

.particle {
  font-size: 20px;
  animation: particle-float 1.5s ease-out forwards;
  text-shadow: 0 0 10px rgba(255, 255, 255, 0.8);
}

/* 爆炸特效 */
.explosion-effect {
  position: absolute;
  pointer-events: none;
  z-index: 90;
}

.explosion-particles {
  position: relative;
  width: 100px;
  height: 100px;
}

.explosion-particle {
  position: absolute;
  width: 8px;
  height: 8px;
  background: radial-gradient(circle, #ff6b6b, #ff8e53);
  border-radius: 50%;
  animation: explosion-burst 1.2s ease-out forwards;
}

.explosion-particle:nth-child(1) { animation-delay: 0s; transform: rotate(0deg); }
.explosion-particle:nth-child(2) { animation-delay: 0.1s; transform: rotate(45deg); }
.explosion-particle:nth-child(3) { animation-delay: 0.2s; transform: rotate(90deg); }
.explosion-particle:nth-child(4) { animation-delay: 0.3s; transform: rotate(135deg); }
.explosion-particle:nth-child(5) { animation-delay: 0.4s; transform: rotate(180deg); }
.explosion-particle:nth-child(6) { animation-delay: 0.5s; transform: rotate(225deg); }
.explosion-particle:nth-child(7) { animation-delay: 0.6s; transform: rotate(270deg); }
.explosion-particle:nth-child(8) { animation-delay: 0.7s; transform: rotate(315deg); }

/* 彩虹特效 */
.rainbow-effect {
  position: absolute;
  pointer-events: none;
  z-index: 70;
}

.rainbow-arc {
  width: 120px;
  height: 60px;
  border: 4px solid transparent;
  border-top: 4px solid #ff0000;
  border-right: 4px solid #ff7f00;
  border-bottom: 4px solid #ffff00;
  border-left: 4px solid #00ff00;
  border-radius: 50%;
  animation: rainbow-rotate 2s ease-out forwards;
  filter: drop-shadow(0 0 10px rgba(255, 255, 255, 0.5));
}

/* 闪电特效 */
.lightning-effect {
  position: absolute;
  pointer-events: none;
  z-index: 90;
}

.lightning-bolt {
  font-size: 80px;
  color: #ffff00;
  text-shadow: 
    0 0 10px #ffff00,
    0 0 20px #ffff00,
    0 0 30px #ffff00,
    0 0 40px #ffff00;
  animation: lightning-strike 1s ease-out forwards;
  filter: drop-shadow(0 0 15px rgba(255, 255, 0, 0.8));
}

/* 神龙特效 */
.dragon-effect {
  position: absolute;
  pointer-events: none;
  z-index: 85;
}

.dragon-body {
  font-size: 100px;
  color: #ff6b35;
  text-shadow: 
    0 0 15px #ff6b35,
    0 0 25px #ff6b35,
    0 0 35px #ff6b35;
  animation: dragon-fly 2.5s ease-in-out forwards;
  filter: drop-shadow(0 0 20px rgba(255, 107, 53, 0.8));
}

/* 凤凰特效 */
.phoenix-effect {
  position: absolute;
  pointer-events: none;
  z-index: 95;
}

.phoenix-body {
  font-size: 120px;
  color: #ff4500;
  text-shadow: 
    0 0 20px #ff4500,
    0 0 30px #ff4500,
    0 0 40px #ff4500,
    0 0 50px #ff4500;
  animation: phoenix-rise 3s ease-in-out forwards;
  filter: drop-shadow(0 0 25px rgba(255, 69, 0, 0.9));
}

/* 星空特效 */
.star-effect {
  position: absolute;
  pointer-events: none;
  z-index: 60;
}

.star {
  font-size: 20px;
  color: #ffffff;
  text-shadow: 
    0 0 5px #ffffff,
    0 0 10px #ffffff,
    0 0 15px #ffffff;
  animation: star-twinkle 1.5s ease-in-out forwards;
  filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.6));
}

/* 动画关键帧 */
/* 普通礼物动画 */
@keyframes gift-float-normal {
  0% {
    transform: translateY(100px) scale(0.5) rotate(-10deg);
    opacity: 0;
  }
  15% {
    transform: translateY(80px) scale(0.8) rotate(-5deg);
    opacity: 1;
  }
  50% {
    transform: translateY(20px) scale(1.1) rotate(0deg);
    opacity: 1;
  }
  85% {
    transform: translateY(-20px) scale(1) rotate(5deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-50px) scale(0.8) rotate(10deg);
    opacity: 0;
  }
}

/* 特殊礼物动画 */
@keyframes gift-float-special {
  0% {
    transform: translateY(100px) scale(0.3) rotate(-20deg);
    opacity: 0;
  }
  10% {
    transform: translateY(90px) scale(0.6) rotate(-15deg);
    opacity: 0.8;
  }
  25% {
    transform: translateY(70px) scale(0.9) rotate(-10deg);
    opacity: 1;
  }
  50% {
    transform: translateY(30px) scale(1.2) rotate(0deg);
    opacity: 1;
  }
  75% {
    transform: translateY(-10px) scale(1.1) rotate(10deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-60px) scale(0.7) rotate(20deg);
    opacity: 0;
  }
}

/* 高级礼物动画 */
@keyframes gift-float-premium {
  0% {
    transform: translateY(120px) scale(0.2) rotate(-30deg);
    opacity: 0;
  }
  8% {
    transform: translateY(100px) scale(0.5) rotate(-20deg);
    opacity: 0.6;
  }
  20% {
    transform: translateY(80px) scale(0.8) rotate(-10deg);
    opacity: 0.9;
  }
  40% {
    transform: translateY(40px) scale(1.3) rotate(0deg);
    opacity: 1;
  }
  70% {
    transform: translateY(0px) scale(1.2) rotate(15deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-80px) scale(0.6) rotate(30deg);
    opacity: 0;
  }
}

/* 豪华礼物动画 */
@keyframes gift-float-luxury {
  0% {
    transform: translateY(150px) scale(0.1) rotate(-45deg);
    opacity: 0;
  }
  5% {
    transform: translateY(130px) scale(0.3) rotate(-35deg);
    opacity: 0.4;
  }
  15% {
    transform: translateY(100px) scale(0.6) rotate(-25deg);
    opacity: 0.7;
  }
  30% {
    transform: translateY(60px) scale(1.0) rotate(-10deg);
    opacity: 0.9;
  }
  50% {
    transform: translateY(20px) scale(1.4) rotate(0deg);
    opacity: 1;
  }
  70% {
    transform: translateY(-20px) scale(1.3) rotate(20deg);
    opacity: 1;
  }
  100% {
    transform: translateY(-100px) scale(0.5) rotate(45deg);
    opacity: 0;
  }
}

/* 光效动画 */
@keyframes shimmer {
  0% {
    transform: rotate(0deg);
    opacity: 0.3;
  }
  50% {
    opacity: 0.6;
  }
  100% {
    transform: rotate(360deg);
    opacity: 0.3;
  }
}

@keyframes light-sweep {
  0% {
    left: -100%;
  }
  50% {
    left: 100%;
  }
  100% {
    left: 100%;
  }
}

/* 不同等级的发光效果 */
@keyframes special-pulse {
  0% {
    box-shadow: 0 8px 25px rgba(138, 43, 226, 0.4), 0 0 20px rgba(138, 43, 226, 0.3);
  }
  50% {
    box-shadow: 0 8px 35px rgba(138, 43, 226, 0.6), 0 0 30px rgba(138, 43, 226, 0.5);
  }
  100% {
    box-shadow: 0 8px 25px rgba(138, 43, 226, 0.4), 0 0 20px rgba(138, 43, 226, 0.3);
  }
}

@keyframes premium-glow {
  0% {
    box-shadow: 0 8px 25px rgba(255, 20, 147, 0.4), 0 0 30px rgba(255, 20, 147, 0.4);
  }
  100% {
    box-shadow: 0 8px 40px rgba(255, 20, 147, 0.6), 0 0 50px rgba(255, 20, 147, 0.6);
  }
}

@keyframes luxury-glow {
  0% {
    box-shadow: 0 8px 25px rgba(255, 215, 0, 0.6), 0 0 40px rgba(255, 215, 0, 0.4), 0 0 60px rgba(255, 20, 147, 0.3);
  }
  100% {
    box-shadow: 0 8px 50px rgba(255, 215, 0, 0.8), 0 0 70px rgba(255, 215, 0, 0.6), 0 0 90px rgba(255, 20, 147, 0.5);
  }
}

@keyframes luxury-shimmer {
  0% {
    transform: rotate(0deg) scale(1);
    opacity: 0.5;
  }
  50% {
    transform: rotate(180deg) scale(1.1);
    opacity: 0.8;
  }
  100% {
    transform: rotate(360deg) scale(1);
    opacity: 0.5;
  }
}

/* 图标动画 */
@keyframes icon-bounce {
  0% {
    transform: scale(1);
  }
  100% {
    transform: scale(1.2);
  }
}

@keyframes icon-rotate {
  0% {
    transform: rotate(0deg) scale(1);
  }
  50% {
    transform: rotate(180deg) scale(1.3);
  }
  100% {
    transform: rotate(360deg) scale(1);
  }
}

@keyframes icon-pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}

@keyframes icon-luxury {
  0% {
    transform: scale(1) rotate(0deg);
  }
  25% {
    transform: scale(1.3) rotate(90deg);
  }
  50% {
    transform: scale(1.6) rotate(180deg);
  }
  75% {
    transform: scale(1.3) rotate(270deg);
  }
  100% {
    transform: scale(1) rotate(360deg);
  }
}

@keyframes particle-float {
  0% {
    transform: translateY(0) scale(0);
    opacity: 0;
  }
  20% {
    transform: translateY(-20px) scale(1);
    opacity: 1;
  }
  80% {
    transform: translateY(-80px) scale(0.8);
    opacity: 0.8;
  }
  100% {
    transform: translateY(-120px) scale(0);
    opacity: 0;
  }
}

@keyframes explosion-burst {
  0% {
    transform: translateX(0) scale(0);
    opacity: 1;
  }
  50% {
    transform: translateX(50px) scale(1);
    opacity: 0.8;
  }
  100% {
    transform: translateX(100px) scale(0);
    opacity: 0;
  }
}

@keyframes rainbow-rotate {
  0% {
    transform: rotate(0deg) scale(0.5);
    opacity: 0;
  }
  20% {
    transform: rotate(72deg) scale(1);
    opacity: 1;
  }
  50% {
    transform: rotate(180deg) scale(1.2);
    opacity: 0.8;
  }
  80% {
    transform: rotate(288deg) scale(1);
    opacity: 0.6;
  }
  100% {
    transform: rotate(360deg) scale(0.3);
    opacity: 0;
  }
}

/* 神话特效动画 */
@keyframes lightning-strike {
  0% {
    transform: scale(0) rotate(0deg);
    opacity: 0;
  }
  10% {
    transform: scale(1.5) rotate(5deg);
    opacity: 1;
  }
  20% {
    transform: scale(1.2) rotate(-3deg);
    opacity: 0.8;
  }
  30% {
    transform: scale(1.8) rotate(8deg);
    opacity: 1;
  }
  40% {
    transform: scale(1.1) rotate(-5deg);
    opacity: 0.7;
  }
  50% {
    transform: scale(1.6) rotate(3deg);
    opacity: 0.9;
  }
  100% {
    transform: scale(0.5) rotate(0deg);
    opacity: 0;
  }
}

@keyframes dragon-fly {
  0% {
    transform: translateX(-200px) translateY(100px) scale(0.3) rotate(-45deg);
    opacity: 0;
  }
  15% {
    transform: translateX(-100px) translateY(50px) scale(0.6) rotate(-30deg);
    opacity: 0.7;
  }
  30% {
    transform: translateX(0px) translateY(0px) scale(1) rotate(0deg);
    opacity: 1;
  }
  50% {
    transform: translateX(100px) translateY(-50px) scale(1.2) rotate(15deg);
    opacity: 1;
  }
  70% {
    transform: translateX(200px) translateY(-100px) scale(1.1) rotate(30deg);
    opacity: 0.8;
  }
  100% {
    transform: translateX(400px) translateY(-200px) scale(0.4) rotate(45deg);
    opacity: 0;
  }
}

@keyframes phoenix-rise {
  0% {
    transform: translateY(200px) scale(0.2) rotate(0deg);
    opacity: 0;
  }
  10% {
    transform: translateY(150px) scale(0.4) rotate(10deg);
    opacity: 0.5;
  }
  25% {
    transform: translateY(100px) scale(0.7) rotate(20deg);
    opacity: 0.8;
  }
  40% {
    transform: translateY(50px) scale(1) rotate(0deg);
    opacity: 1;
  }
  60% {
    transform: translateY(0px) scale(1.3) rotate(-10deg);
    opacity: 1;
  }
  80% {
    transform: translateY(-50px) scale(1.1) rotate(-20deg);
    opacity: 0.8;
  }
  100% {
    transform: translateY(-150px) scale(0.3) rotate(-30deg);
    opacity: 0;
  }
}

@keyframes star-twinkle {
  0% {
    transform: scale(0.5) rotate(0deg);
    opacity: 0.3;
  }
  25% {
    transform: scale(1.2) rotate(90deg);
    opacity: 1;
  }
  50% {
    transform: scale(0.8) rotate(180deg);
    opacity: 0.6;
  }
  75% {
    transform: scale(1.5) rotate(270deg);
    opacity: 0.9;
  }
  100% {
    transform: scale(0) rotate(360deg);
    opacity: 0;
  }
}

/* 签到弹窗样式 */
.attendance-modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.7);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.attendance-modal {
  background-color: #ffffff;
  border-radius: 20rpx;
  padding: 40rpx;
  margin: 40rpx;
  max-width: 600rpx;
  width: 90%;
  box-shadow: 0 10rpx 30rpx rgba(0, 0, 0, 0.3);
  animation: modalSlideIn 0.3s ease-out;
}

@keyframes modalSlideIn {
  from {
    transform: translateY(-50rpx);
    opacity: 0;
  }
  to {
    transform: translateY(0);
    opacity: 1;
  }
}

.attendance-header {
  text-align: center;
  margin-bottom: 30rpx;
  border-bottom: 2rpx solid #f0f0f0;
  padding-bottom: 20rpx;
}

.attendance-title {
  font-size: 36rpx;
  font-weight: bold;
  color: #333333;
  display: block;
  margin-bottom: 10rpx;
}

.attendance-countdown {
  font-size: 28rpx;
  color: #ff6b6b;
  font-weight: bold;
  display: block;
}

.attendance-content {
  text-align: center;
  margin-bottom: 40rpx;
}

.attendance-message {
  font-size: 32rpx;
  color: #666666;
  line-height: 1.5;
  display: block;
}

.attendance-actions {
  display: flex;
  justify-content: space-around;
  gap: 20rpx;
}

.attendance-btn {
  flex: 1;
  height: 80rpx;
  border-radius: 40rpx;
  font-size: 32rpx;
  font-weight: bold;
  border: none;
  cursor: pointer;
  transition: all 0.3s ease;
}

.confirm-btn {
  background-color: #4CAF50;
  color: white;
}

.confirm-btn:hover {
  background-color: #45a049;
  transform: translateY(-2rpx);
}


</style>